6

の2回目の呼び出しで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

これがエラーを再現するJSfiddleですhttp://jsfiddle.net/KjkQ2/

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)内で呼び出す場合は、 (ブラウザ.fn内の)内で呼び出されます。これで、基本的に前に作成した関数オブジェクトを上書きする設定を行っています。global contextwindowwindow.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の優れた機能です。これは、ここでの問題です。関数を呼び出すと、「そのようにthisは常にグローバルオブジェクトを参照します。

于 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 に答える