3

JSON で記述されたコードを解釈する JavaScript VMに対する私自身の回答で、JavaScript クロージャーの「パブリック」プロパティには「プライベート」関数ではアクセスできないと述べました。

その投稿で与えられた例は

function anobject(){
    var privatefunction = function(){
        //publicfunction(); //wrong; you have no access to it
        console.log(this); //refer to the global object, not the object creating
    };
    this.publicfunction = function(){
        console.log(this); //refer to the object creating
    }
}

privatefunctionその理由は、下位互換性の問題がグローバルオブジェクトに属している必要があるためだと思います。したがって、パブリック関数は、のプロパティに割り当てられた無名関数にすぎませんthispublicfunctionこれは、最初への参照が必要なため、呼び出しが失敗する理由を説明していますthis

ただし、次の修正はまだ機能しません。

function anobject(){
    var privatefunction = function(){
        //publicfunction(); //wrong; you have no access to it
        console.log(this); //refer to the object creating
    }.bind(this);
    this.publicfunction = function(){
        console.log(this); //refer to the object creating
    }
}

privatefunctionオブジェクトの作成にバインドする必要があることを明示的に指定しているため、呼び出しpublicfunctionは機能するはずですが、機能しません。私は次のことをしなければなりません:

function anobject(){
    var privatefunction = function(){
        this.publicfunction();
        console.log(this); //refer to the object creating
    }.bind(this);
    this.publicfunction = function(){
        console.log(this); //refer to the object creating
    }
}

別の回避策(私が使用している方法)は次のとおりです。

function anobject(){
    var privatefunction = function(){
        publicfunction();
        console.log(this); //refer to the object creating
    };
    var publicfunction = function(){
        console.log(this); //refer to the object creating
    }
    this.publicfunction = publicfunction;
}

では質問部分です。この動作の背後にある理由は何ですか? thisaccessのプロパティを明示的に指定せずに無効にすることで、何を回避しようとしていますか?

更新: 質問の主な部分は次のとおりです: インタープリターがスコープチェーンで名前を見つけられない場合、なぜプロパティを調べるべきではないのthisですか?

4

2 に答える 2

4

ここでの問題は、参照thisが関数/メソッドの呼び出し元によって決定されることです。たとえば、次のようになります。

function anobject(){
    // here "this" is the object
    var privatefunction = function(){
        // here "this" is the object **that called privatefunction()**
    };
    this.publicfunction = function(){
        // this method will always be called by the object, so "this" is the object
    }
}

あなたが望むものを達成するために、これを試すこともできます:

function anobject(){
    var that = this;
    var privatefunction = function(){
        [do what you like using "that"]
    };
    this.publicfunction = function(){
        [here you can use "this" directly, or "that"]
    }
}

こちらのJavaScript スコープの仕組みも参照してください。 JavaScript の変数のスコープとは? そしてウェブ上。

于 2012-11-28T12:52:24.920 に答える
1

2 番目の例では、 objectのプロパティpublicfunction()として宣言されています。this

this.publicfunction = function(){
    console.log(this);
}

したがって、この関数はその名前publicfunction()で直接アクセスできず、コンテキストから独立しています。関数は実際にはどのコンテキストにも属していませんが、プロパティであるオブジェクトに属しています。

あなたの例では、 をprivatefunction()呼び出すと、のプロパティにアクセスできないためではなく、 という名前の変数publicfunction()として宣言された関数がないため、エラーが発生します。publicfunction()this

function anobject(){
    var privatefunction = function(){
        //publicfunction(); // You cannot call publicfunction() because there is
                            // no function defined with this name
    }.bind(this);
    this.publicfunction = function(){
        console.log(this);
    }
}

この例を見てください。publicfunction()内でもアクセスできませんanobject():

function anobject(){
    this.publicfunction = function() {
        console.log(this);
    }
    // publicfunction(); // Wrong because publicfunction()
                         // was not defined as a variable
}

ただし、がのコンテキスト内で変数publicfunction()として定義されている場合、この関数はその名前でアクセスできます。たとえば、次のクロージャ内で簡単に宣言できます。anobject()function publicfunction()anobject()

function anobject(){
    function publicfunction() {
        console.log(this);
    }
    publicfunction(); // You can access publicfunction() here
}

ただし、この場合、publicfunction()の実行コンテキスト外ではアクセスできないanobject()ため、「プライベート」関数と見なすことができます。

var a = new anobject();
if(typeof a.publicfunction === 'undefined')
    console.log('Public function is undefined outside of anobject()');

その結果、thisキーワードを使用して を宣言するのはそのためpublicfunction()です。これにより、 のコンテキスト外でアクセスできるようになりますがanobject()、そうすると、この関数は のプロパティとしてのみ定義されますanobject()

したがって、この関数にアクセスする唯一の方法は、次のように呼び出すことthis.publicfunction()です。

function anobject(){
    var privatefunction = function(){
        this.publicfunction();
        console.log(this);
    }.bind(this);
    this.publicfunction = function(){
        console.log(this);
   }
}

キーワードに関する詳細this: 「this」キーワードは関数内でどのように機能しますか?

JavaScript の変数とプロパティ: http://javascriptweblog.wordpress.com/2010/08/09/variables-vs-properties-in-javascript/

于 2012-11-28T13:27:28.063 に答える