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);

显然 this 是调用 publicMethod 时的对象本身,但在 privateMethod 中设置为全局对象。我知道它可以通过改变来解决:

      return privateMethod();

至:

      return privateMethod.call(this);

我知道当一个函数嵌套在一个函数中时,这个 get 会丢失,但没想到这里会出现这种情况。我是否在这里遇到了这个 JavaScript 错误,或者有什么我根本不明白的地方?

4

2 回答 2

2

你在打电话foo.bar()。这意味着函数bar()被调用foo,意思thisfoo在里面bar()

在您的情况下foo一个Foo对象 obj,并且bar()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 回答