0

JavaScript でクラスをコーディングしましたが、プライベート関数内のパブリック プロパティの 1 つを変更しようとしています。

これが私のコードの例です:

MyClass = function(callback){

    this.tabs = [];
    var tabs_callback = function(){};

    this.setTabsCallback = function(callback) {
        tabs_callback = callback;
    }

    var _doStuff = function(callback) {

        // doing stuff

        this.tabs = [1, 2, 3];

        console.log("Inside doStuff");
        console.log(this.tabs);

        tabs_callback();
    }

    this.doStuff = function() {
        _doStuff();
    }
}


var myObject = new MyClass();

myObject.setTabsCallback(function () {

    console.log("Inside callback");
    console.log(myObject.tabs);
});

myObject.doStuff();

そして、これがコンソールに表示されるものです:

Inside doStuff
[ 1, 2, 3 ]
Inside callback
[]

コールバック関数から変更を確認できないのはなぜですか?

4

4 に答える 4

1

デフォルトでは、JS はレキシカル コンテキスト バインディングを使用せず、通常の関数を呼び出すと、(または厳密モードの場合)にthisデフォルト設定されます。windownull

これを回避する方法はたくさんあります:this上記のように、変数に保存できます。100% のケースで機能します。

Function#bindまた、メソッドを使用して _doStuff をコンテキストに明示的にバインドすることもでき_doStuff = _doStuff.bind(this)ます_doStuff.bind(this)()。IE9 より前の IE (および、おそらく、他のブラウザーのいくつかは、よくわかりません) は をサポートしていませんbind

最後に、上でも述べたように、矢印関数を使用できます。それらは字句バインディングを使用thisし、期待どおりになります。アロー関数は ES6 から利用できますが、このようなコンストラクタを作成している場合、それは ES6 ではありません。

于 2016-09-27T14:43:00.347 に答える
1

このキーワードを参照してください。アロー関数を使用すると、これらの問題の多くを防ぐことができます。

var _doStuff = (callback) => { ...

それでも、あなたはそれを認識する必要があります。

于 2016-09-27T14:30:07.817 に答える
1

_doStuf次のような関数を介して呼び出される場合

this.doStuff = function() {
                 _doStuff();
               }

_doStuffグローバルオブジェクトにバインドされています。したがって、その定義を にバインドするか、関数を呼び出すときにthis使用する必要があります。したがって、次のようにコードを変更すると役立ちます。.call(this)_doStuff

MyClass = function(callback){

    this.tabs = [];
    var tabs_callback = function(){};

    this.setTabsCallback = function(callback) {
        tabs_callback = callback;
    }

    var _doStuff = function(callback) {

        // doing stuff

        this.tabs = [1, 2, 3];

        console.log("Inside doStuff");
        console.log(this.tabs);

        tabs_callback();
    } // <<< you can either use .bind(this) here 

    this.doStuff = function() {
        _doStuff.call(this);  // <<< or use .call(this) here to bind _doStuff to the this
    }
}


var myObject = new MyClass();

myObject.setTabsCallback(function () {

    console.log("Inside callback");
    console.log(myObject.tabs);
});

myObject.doStuff();

于 2016-09-27T14:47:07.310 に答える
1

は関数として定義されているため_doStuff、独自のコンテキストを持ちます。そのため、プライベート関数の外部で定義しthisた にアクセスできません。this.tabs

これを解決するには、2 つの簡単な方法があります。

thisまず、関数の外部への参照を保持するプライベート変数を簡単に作成できます。

...
var that = this;
var _doStuff = function(callback) {
    // inside _doStuff, use "that" instead of "this"
...

または、2 番目に、代わりにアロー関数を使用することもできます。アロー関数は、Javascript に比較的新しく追加されたものです。独自のthis参照を持つ個別のコンテキストを作成しないため、thisオブジェクトを使用する場合でも、関数の外部と同じオブジェクトを参照するため、関数は正しく機能します。

....
var _doStuff = (callback) => {
    // now _doStuff doesn't create a new "this" object, so you can still access the one from outside
...
于 2016-09-27T15:01:43.200 に答える