0

javascript が関数を渡す方法を理解しようとしていますが、プロトタイプ関数が関数コンストラクターで定義された var にアクセスできないのに、コンストラクターで定義された関数が var にアクセスできる理由を少し理解するのに少し問題があります。動作するコードは次のとおりです。

   var model = function model() {
       this.state = 1;
       this.GetState =   (function(scope){
           return function(){ return scope.state;};
       })(this);
   }

    var othermodel = function othermodel(mdl) {
        this.GetStateFn = mdl.GetState;
    }

    othermodel.prototype.WriteState = function() {
        console.log(this.GetStateFn.call());
    };

    var m = new model();
    var o = new othermodel(m)


    o.WriteState();

これは機能し、理にかなっています - GetState() 関数は this.state にアクセスできます。

ただし、次のように GetState を作成すると:

 model.prototype.GetState =   (function(scope){
        return function(){ return scope.state;};
    })(this);

結果は、スコープが定義されていないというエラーになります。

これまでのモデルで関数のコピーが必要ないため、プロトタイプメソッドでこれを機能させたいと思いますが、モデルの特定のインスタンスにアクセスできないため、プロトタイプが機能しないようです。

それで、誰かが私にa)これをプロトタイプで動作させるために何をする必要があるか(私ができると仮定して)、b)プロトタイプで動作させることができない場合、その理由は何ですか?問題の根底をよりよく理解できます。

4

4 に答える 4

2

このように単純に関数を記述しない理由

model.prototype.GetState = function() { return this.state; }

var othermodel = function othermodel(mdl) {
    this.GetStateFn = mdl.GetState.bind(mdl);
}

othermodel.prototype.WriteState = function() {
    console.log(this.GetStateFn.call());
};

ほとんどの場合、 のようなコードを実行するため、上記のコードは機能しますm.GetState()。これは、関数をオブジェクト メソッドとして呼び出す例です。その場合、thisは object を指すことが保証されますm。試作品のチェーンの仕組みを知っているようだから、そこには行かないよ。

関数参照を他のモデルに割り当てるときは、 を使用し.bindて 内GetStateで が をthis指すようにしmdlます。のリファレンスbind: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind

元の IIFE は、実際には bind の実装でした。問題は、の値thisが間違っていたことです。現在、モデル関数を他の関数に割り当てる必要があるたびにbind、常に を使用する必要があります。質問に node.js というタグを付けました。これは、node.js のプロトタイプと ES5 互換のブラウザーでbind利用できます。Functionをサポートしていない古いブラウザまたは環境で上記のコードを実行する必要がある場合は、IIFEbindに置き換えてください。bind

コードが機能しない理由については、

model.prototype.GetState =   (function(scope){
    return function(){ return scope.state;};
})(this);

ここでthisは、最終的なモデル オブジェクト ( ) を参照しませんmthisjavascript の 5 つのオプションのいずれかを参照できます。参照: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this

上記のコードがスクリプトタグ内のhtmlファイルにあると仮定しましょう。次にthis、window オブジェクトを参照します。windowと呼ばれるプロパティがないstateため、undefined. console.log(this.m, this.o)スクリプトの最後にすると、それぞれの と オブジェクトが表示されmますo

于 2012-11-28T19:42:35.167 に答える
2

次のように定義すると:

var model = function model() {
    this.state = 1;
    this.GetState =   (function(scope){
        return function(){ return scope.state;};
    })(this);
}

無名関数が宣言され、すぐに実行されます。thisその自己実行関数にパラメーターとして渡されます。その結果、新しい関数が返されますが、この関数にはscopeクロージャーにパラメーターが含まれているため、スコープが終了した後にアクセスできます。その結果、呼び出された関数は、stateその「囲まれた」this(scope閉じられたもの) のプロパティに引き続きアクセスできます。

次のように定義すると:

model.prototype.GetState =   (function(scope){
    return function(){ return scope.state;};
})(this);

メカニズムは同じですが、そうでthisはありません。これは、上記のコードを実行するスコープのコンテキストです。グローバル スコープで実行されると仮定すると、windowオブジェクトになります。

于 2012-11-28T19:47:08.877 に答える
1

古いブラウザーでのサポートのために使用したくない場合はbind、これを試すことができます。

http://jsfiddle.net/j7h97/1/

var model = function (state) {
    this.state = state || new Date().getTime();
};

model.prototype.GetState = function () {
    return this.state;
};

model.prototype.WriteState = function () {
    console.log("model WriteState: " + this.GetState());
};

var othermodel = function othermodel (mdl) {
    this.GetStateFn = function () {
        return mdl.GetState.call(mdl);
    };
};

othermodel.prototype.WriteState = function () {
    console.log("othermodel WriteState: " + this.GetStateFn());
};

var model1 = new model();
model1.WriteState();
var othermodel1 = new othermodel(model1);
othermodel1.WriteState();

var model2 = new model();
model2.WriteState();
var othermodel2 = new othermodel(model2);
othermodel2.WriteState();

なしでやりたいことができるようですbindmodel.prototype.WriteStateテスト目的でを作成しました。

于 2012-11-28T20:45:03.467 に答える
0

呼ばれる場所によります。グローバル スコープ内にある場合thisは、モデルを参照しません。ブラウザで実行している場合は、window代わりにグローバル オブジェクトを参照します。

于 2012-11-28T19:47:09.180 に答える