1

私はこのようなことを試みています:

(function() {
  var Foo, foo;

  Foo = function(proto) {
    var obj, privateMethod, publicMethod;
    privateMethod = function() {
      return console.log("private", this);
    };
    publicMethod = function() {
      console.log("public", this);
      return privateMethod();
    };
    obj = Object.create(proto);
    obj.bar = publicMethod;
    return obj;
  };

  foo = new Foo({
    baz: "dooz"
  });

  foo.bar();

}).call(this);

明らかに、これはpublicMethodが呼び出されたときのオブジェクト自体ですが、privateMethodのグローバルオブジェクトに設定されます。私はそれが変更することによって解決できることを知っています:

      return privateMethod();

に:

      return privateMethod.call(this);

関数が関数にネストされていると、これが失われることは知っていますが、ここではそのようなケースを予期していませんでした。ここでこのJavaScriptのバグに遭遇しますか、それとも私がまだ理解していない何かがありますか?

4

2 に答える 2

2

あなたは呼んでいfoo.bar()ます。これは、関数bar()がで呼び出されることfooを意味します。thisつまり、foo内部にありbar()ます。

あなたの場合fooオブジェクトでありFoo です。objbar()publicMethod

publicMethod()呼び出すとprivateMethod()、コンテキストがないためthis、グローバルthiswindow)になります。

于 2012-05-01T18:52:37.820 に答える
2

javascriptのコンテキスト(this)は、関数の呼び出し方法によって設定され、関数自体のプロパティではありません。

obj.bar = function() { console.log(this) };
obj.bar()    // obj
obj['bar']() // obj

// But break the function off the object, and this changes
fn = obj.bar
fn() // window

この例が示しているのは、そこにドット構文が設定されていることthisです。obj.bar()のシンタックスシュガーと考えてくださいobj.bar.call(obj)

したがってthis、外部コードで呼び出される方法により、パブリックメソッドは正しくなります。

foo.bar();

ただし、プライベートメソッドは、レシーバーがまったくない状態で呼び出されます。

return privateMethod();

したがって、コンテキストは割り当てられず、デフォルトでグローバルオブジェクトになります。


したがって、コンストラクターでこれらの関数を作成している場合は、ある程度の柔軟性があります。

thisコンストラクター内のの適切な値を他の何かに割り当て、それをプライベート関数で使用することができます。(おそらく最良のオプション)

var self = this;
privateMethod = function() {
  return console.log("private", self);
};

または、JSターゲットエンジンがサポートされている場合Function.prototype.bind(残念ながら、すべてがサポートされているわけではありません)、次のことができます。

privateMethod = function() {
  return console.log("private", this);
}.bind(this);

これは、何があっても、コンテキストが割り当てられた関数を返します。

または、手動でバインドすることもできます。

_privateMethod = function() {
  return console.log("private", this);
}

Foo = function(proto) {
  privateMethod = function() {
    _privateMethod.call(this);
  }
}
于 2012-05-01T18:53:07.317 に答える