6

你能解释一下为什么第二次调用fn会出错吗?代码如下。

function Test(n) {
  this.test = n;

  var bob = function (n) {
      this.test = n;
  };

  this.fn = function (n) {
    bob(n);
    console.log(this.test);
  };
}

var test = new Test(5);

test.fn(1); // returns 5
test.fn(2); // returns TypeError: 'undefined' is not a function

这是一个重现错误http://jsfiddle.net/KjkQ2/的 JSfiddle

4

3 回答 3

6

您的bob函数是从全局范围调用的。因此,this.test指向一个名为的全局变量test,该变量正在覆盖您创建的变量。如果你跑console.log(window.test),你会发生什么。

为了使您的代码按预期运行,您需要以下之一

function Test(n) {
  this.test = n;

  // If a function needs 'this' it should be attached to 'this'       
  this.bob = function (n) {
      this.test = n;
  };

  this.fn = function (n) {
    // and called with this.functionName
    this.bob(n);
    console.log(this.test);
  };
}

或者

function Test(n) {
  this.test = n;

  var bob = function (n) {
      this.test = n;
  };

  this.fn = function (n) {
    // Make sure you call bob with the right 'this'
    bob.call(this, n);
    console.log(this.test);
  };
}

或基于闭包的对象

// Just use closures instead of relying on this
function Test(n) {
  var test = n;

  var bob = function (n) {
      test = n;
  };

  this.fn = function (n) {
    bob(n);
    console.log(test);
  };
}
于 2012-10-17T20:51:12.620 回答
3

当调用bob(n)inside时.fn,它​​在global context(window在浏览器中) 内调用。现在,您正在设置window.test = n;它基本上会覆盖您的功能test之前创建的函数对象。

如果我们把它写得更明确,它会变得更明显:

// in the global scope, `test` gets written to the `global object`
// window.test = new Test(5);
var test = new Test(5);

test.fn(1); // returns 5
test.fn(2); // returns TypeError: 'undefined' is not a function

bob()您可以通过使用显式上下文调用来“解决”此问题.call(),例如:

this.fn = function (n) {
   bob.call(this,n);
   console.log(this.test);
};

这里的祸根是, 的值this是在运行时动态分配的。不要误会我的意思,它实际上是 ECMAscript 的一个很棒的特性——这只是你的问题。当您调用一个函数时,“ just like thatthis将始终引用全局对象。

于 2012-10-17T20:51:07.980 回答
0

你想打电话bob.call(this, n),不只是bob(n)

当您调用 时bob(n), 的值this不是您的对象,而是window. 因此,您的test变量将替换为1.

在 jsFiddle 中,代码被包裹在一个函数中,所以一window.test开始并不存在。

于 2012-10-17T20:52:19.307 回答