1

問題

こんにちは、私は JavaScript の初心者であり、Python と Java の非常にオブジェクト指向の世界から来ました。これは私の免責事項です。

以下に 2 つのコードのチャンクがあります。1 つは JavaScript で、もう 1 つは Coffeescript です。Meteor.js アプリケーションのサーバーでそれらを実行しようとしています。私が経験している問題は、バインドされたメソッド「this.printSomething」をコールバックとして使用して関数「setInterval」を呼び出すときに、そのコールバックが実行されると、インスタンスのスコープが失われ、「this.bar」が未定義になることです! JavaScript または coffescript コードが機能しない理由を誰かに説明してもらえますか?

JavaScript の実装

function Foo(bar) {
  this.bar = bar;

  this.start = function () {
    setInterval(this.printSomething, 3000);
  }

  this.printSomething = function() {
    console.log(this.bar);
  }
}

f = new Foo(5);
f.start();

Coffeescript の実装

class foo
    constructor: (bar) ->
        @bar = bar

    start: () ->
        Meteor.setInterval(@printSomething, 3000)

    printSomething: () ->
        console.log @bar

x = new foo 0
x.start()
4

3 に答える 3

2

FoosetInterval コールバックでコンテキストが失われます。Function.bindを使用してコンテキストを次のように設定し、コールバック関数参照のコンテキストをFooインスタンスに戻すことができます。

setInterval(this.printSomething.bind(this), 3000);

呼び出しで

setInterval(this.printSomething, 3000);

コールバック メソッドはグローバル コンテキスト (Web の場合はウィンドウ、ノードなどのテナントの場合はグローバル) を取得するため、グローバル コンテキストを参照するため、barそこでプロパティを取得しません。this

フィドル

あるいは単に

 this.printSomething = function() {
     console.log(bar); //you can access bar here since it is not bound to the instance of Foo
  }
于 2013-09-11T03:11:40.143 に答える
1

をキャプチャするクロージャを作成することもできますthis。このような:

var self = this;
this.start = function () {
    setInterval(function(){
       self.printSomething();
    }, 3000);
}
于 2013-09-11T03:22:02.110 に答える
0

関数を入力すると、JavaScript で新しいスコープが取得されます。親スコープから継承できますが、値がthis変わります。thiscoffeescript では、新しいスコープに入る前に参照を基本的に保持する太い矢印 (ecmascript 6 の一部になるように見えます) を使用できます。

class foo
    constructor: (bar) ->
        @bar = bar

    start: () =>
        Meteor.setInterval(@printSomething, 3000)

    printSomething: () =>
        console.log @bar

x = new foo 0
x.start()

JavaScriptでこの種のものを処理する標準的な方法は、参照しthisたいポイントでへの参照を作成し、その参照をスコープ外の呼び出しで使用することです...

function Foo(bar) {

  // make reference to `this` at the point
  // where you want to use it from
  self = this;

  self.bar = bar;

  self.start = function () {
    setInterval(self.printSomething, 3000);
  }

  self.printSomething = function() {
    console.log(self.bar);
  }
}

f = new Foo(5);
f.start();
于 2013-09-11T07:45:25.650 に答える