this
JavaScriptのオブジェクトについてはある程度理解できたと思います。オブジェクト、コールバック、およびイベントとハンドラーの両方を扱う場合、太古の昔から問題はありませんでした。しかし、今ではすべてが変わりました。
私は JavaScript に夢中になりました。純粋な JS です。つまり、jQuery、prototype.js、dojo ではありません。当然のことながら、私はクロージャーを使用するようになりました。ただし、場合によっては、this
ここで不意を突かれることがあります。このスニペットを 1 つ取ります。
function anyFunc(par)
{
//console.log(par);
console.log(this);
}
function makeClosure(func)
{
return function(par)
{
return func(par);
}
}
var close = makeClosure(anyFunc);
close('Foo');
var objWithClosure = {cls:makeClosure(anyFunc),prop:'foobar'};
objWithClosure.cls(objWithClosure.prop);
var scndObj = {prop:'Foobar2'};
scndObj.cls = makeClosure;
scndObj.cls = scndObj.cls(anyFunc);
scndObj.cls(scndObj.prop);
3 つのケースすべてthis
で、window オブジェクトとしてログに記録します。もちろん、簡単に修正できます。
function makeClosure(func)
{
return function(par)
{
return func.call(this,par);
}
}
この修正は機能します。私が知る必要があることを説明せずに、人々がこれに答えるのを避けるためにここに置きます:なぜこれはここでのように振る舞うのですか?
呼び出し元が実質的にクロージャーが属するオブジェクトであることを保証します。私が理解できないのはこれです: 案の定this
、最初のケースでは window オブジェクトを指しますが、他のケースではそうすべきではありません。this
戻る直前に makeClosure 関数にログインしようとしましたが、オブジェクトではなく、オブジェクト自体がログに記録されましたwindow
。しかし、実際のクロージャが使用されるthis
と、window オブジェクトへのポイントに戻ります。なんで?
私が考えることができる唯一のことは、anyFunc
関数を引数として渡すことによって、実際に を渡しているということですwindow.anyFunc
。だから私はこの簡単な修正を試みました:
function makeClosure(func)
{
var theFunc = func;
return function(par)
{
theFunc(par);
}
}
期待どおりの結果でthis
、オブジェクトを指すようになりましたが、やはり: なぜでしょうか? いくつかのアイデアがあります (theFunc
ローカル スコープの関数への参照です [ this > private: theFunc
]?) が、ここには JS に関してもっと多くのノウハウを持っている人がいると確信しているので、いくつか取得したいと考えていました。より多くの説明またはそれらから読む価値のある記事へのリンク...
ありがとう
アップデート
ここにフィドルがあります。何かを省略した可能性がありますが、ここではあらゆる種類のものをログに記録します;)
編集/更新 2
私を混乱させるケースはここにあります。
最終編集
わかりました、これはかなり厄介な投稿になっています。明確にするために:私が期待していたのは、これに似た動作でした:
function makeClosure()
{
function fromThisFunc()
{
console.log(this);
}
return fromThisFunc;
}
var windowContext = makeClosure();
windowContext();
var objectContext = {cls:makeClosure()};
objectContext.cls();
私を捕まえたのは、関数anyFunc
が正しいスコープ内で宣言されていなかったためthis
、ウィンドウ オブジェクトを指していたことです。これは、ウェブ上のどこかで見つけた古代の巻物を読んでわかりました。
しかし、globalVar によって参照されるようになった関数オブジェクトは、それが作成された実行コンテキストに属する Activation/Variable オブジェクトを含むスコープ チェーンを参照する [[scope]] プロパティで作成されたため、もう少し複雑なことが起こりました (そしてグローバル オブジェクト)。globalVar によって参照される関数オブジェクトの実行では、その [[scope]] プロパティからのスコープ チェーン全体を、呼び出しごとに作成された実行コンテキストのスコープに追加する必要があるため、Activation/Variable オブジェクトをガベージ コレクションすることはできません。それ。
だから私がする必要があったのは、物事を複雑にするのではなく単純化することでした:
function fromThisFunc()
{
console.log(this);
}
function makeClosure(funcRef)
{
//some code here
return funcRef;
}
それはうまくいくはずですよね?
PS: Alnitak の回答は除外しますが、Felix Kling の忍耐と情報に特に感謝します。