1

クロージャーの作成に失敗した理由を自分で説明することはできませんundefined。以下のコードを使用します。

function A() {
 this.p1=1;
 this.p2=2;
 this.f1=function(){
    alert(this.p1);
 }
 this.f2=function(){
    alert(this.p2);
    }
 this.action=function(param){
    if (param=='1')
        return this.f1;//by case
    else if (param=='2')
        return this.f2;
    };
}

var v=new A();
v.action("1")();
4

6 に答える 6

4

それは閉鎖とは何の関係もありません。

メソッドから関数参照を返しています。これを呼び出すと、オブジェクト内のメソッドとして実行されることが期待されますが、グローバルスコープをコンテキストとして持つ関数として実行されます。

callこのメソッドを使用して、オブジェクトのコンテキストで関数を呼び出します。

v.action("1").call(v);
于 2012-09-01T22:31:02.203 に答える
1

関数は特定のこれにバインドされていません。つまり、次のようになります。

(function() { console.log(this) })(); // Window

callメソッドを使用するか、(より適切に).bindメソッドを使用できます(古いブラウザーの場合は必ずポリフィルしてください)。

function A() {
 this.p1 = 1;
 this.p2 = 2;
}
A.prototype.f1 = function() {alert(this.p1)};
A.prototype.f2 = function() {alert(this.p2)};
A.prototype.action = function(param) {
  if ('1' == param) {
    return this.f1.bind(this);
  } else if (param == '2') {
    return this.f2.bind(this);
  }
};

var v = new A();
v.action("1")(); // 1

bindメソッドは、bindの引数にこのセットを設定して元の関数を呼び出す新しい関数を返します。MDNに関するFunction.prototype.bindドキュメント

v.action("1")とほぼ同じですaction.call(v, "1")

于 2012-09-01T22:36:36.410 に答える
1

クロージャが何であるかを100%確信していないように私には見えます...あなたのコードから始めて:

function A()
{
    this.p1=1;//public
    var p2=2;//private
    this.f1=function()
    {
        alert(this.p1);
    };
    this.f2=function()
    {
        alert(p2);
    };

ここではp2、コンストラクターのスコープに対してローカルな変数として定義しましたが、パブリックメソッドf2 その値にアクセスし、変更することもできます。それはクロージャです:それ自身の特定のスコープ内に含まれるコード/データ。次のコードで何をしているのか:

    this.action=function(param)
    {
        if (param=='1')
        {
            return this.f1;
        }
        return this.f2;
    };
}
var v=new A();
v.action("1")();

クロージャとはほとんどまたはまったく関係がなく、関数への参照を返します(この特定のケースではオブジェクトメソッドです)。なぜ、これはpointそれが由来するオブジェクトではないのですか?単純:

var foo = {name:'someObject'};
foo.retVal = v.action('1');//returns function
//much later:
foo.retVal();

thisそれでも、あなたは指摘することを期待しvますか?そして、それはデバッグするのが地獄ではないでしょうか?関数(メソッドかどうか)を呼び出すとthis、関数が呼び出されるコンテキストオブジェクトのポインタになります。が戻ると、あなたの例では、関数はグローバルオブジェクトに返されます。したがって、これはまたはv.action('1')を指します。thiswindow

于 2012-09-01T22:40:08.790 に答える
0

このようなクロージャの内部では、「this」は実際には後で呼び出されたときのウィンドウを指します。これを回避するには、「this」を「that」などの別の変数に割り当てる必要があります。

function A() {
var that = this;
 that.p1=1;
 that.p2=2;
 that.f1=function(){
    alert(that.p1);
 }
 that.f2=function(){
    alert(that.p2);
    }
 that.action=function(param){
    if (param=='1')
        return that.f1;//by case
    else if (param=='2')
        return that.f2;
    };
}

var v=new A();
v.action("1")();
于 2012-09-01T22:34:12.697 に答える
0

ネストされた関数の内部にthisは別の意味があります。変数を使用して内部に参照を渡してみてください。jsfiddleを参照してください。

于 2012-09-01T22:34:28.187 に答える
0

あなたが意図したように

v.action("1")

として定義された関数を返します

function(){
    alert(this.p1);
}

行ったように、角かっこを追加して呼び出すこともできます。ただし、thisその関数のinはグローバルオブジェクトにバインドされます(ブラウザではwindow)。そしてwindow.p1ですundefined。それが出力として得られるものです。

すでに述べたように、角かっこの代わりにthis関数を呼び出すことで、関数に何を含めるかを決定できます。call

v.action("1").call(v);

JavaScriptでの意味thisは非常に紛らわしいです。私が理解するのに役立った説明は、セクション3.3にあります。10分でのJavascriptのこの(ひどい災害)の意味(ドキュメント全体は10分以上かかりますが読む価値があります)。

于 2012-09-01T22:56:32.260 に答える