アップデート
わかりやすくするために:@FelixKing:はい、this
呼び出したときにまだ定義されていないことを期待していました。そのwindow.foo()
理由は次のとおりです。
function foo()
{
console.log('I am a function');
}
(ほぼ)次のものと同じです:
var foo = function()
{
console.log('I am a function');
}
そしてfoo === window.foo
trueと評価された場合、両方が同じように動作することを期待します。関数が変数であり、JSがグローバルオブジェクトにフォールバックする場合(関数x内では、変数は宣言されていませんが、それを使用すると、JSは、問題の変数が見つかるまで、グローバルオブジェクトまでのすべてのスコープをバブルアップします。または、グローバルレベルで作成します)、window
オブジェクトを事前に指定するかどうかは関係ありません。しかし、そうすると、私が予期していなかった動作が変化します。
なぜこれが当てはまるのか(変数ではなくメソッドを定義している)については直感がありますが、グローバルオブジェクトの場合、それらの間にほとんど違いはありません。本当のログなど...しかし私は何var c = 'Variable'; console.log(window.c === c);
を知りたいのですか違いは実際には、そしてそれがどのように機能するか(すべてのレベルで)です。
私はそれを受け入れるfoo.apply(this,[]);
か、グローバルオブジェクトをポイントするfoo.apply(window,[]);
ように強制することを許可する準備ができていますが、 。グローバルオブジェクトをシールドするために厳格なものがある場合、これはバックドアを大きく開いたままにしていると言えます。たとえば、変数の値によっては、関数を呼び出すことがあります。そのために、厳密かどうかにかかわらず、それはグローバルオブジェクトを指すことを意味しますが、関数を直接呼び出す場合はそうではありません。つまり、私の考えでは、矛盾です。this
window.foo();
window[myVar]();
this
this
strictモードのキーワードで奇妙な動作が発生しました。誤解しないでください。厳密な関数でthis
は定義されていないことがわかっています。私が紛らわしいと思うのは、それがグローバルオブジェクト(または、さらに言えば、他のオブジェクト)を指すように強制され、strictモードによって提供されるセーフティネットを効果的に損なう可能性があることです。これには他の意味もあります。このコードを考えてみましょう:this
'use strict';//using strict everywhere
(function(Global)
{
var closureObject = {};
Global.foo = function()
{
closureObject.setIn = closureObject.setIn || 'Set in foo';
console.log(this);
console.log(this === Global);
bar();
bar.apply(this);
return (this !== Global ? this : undefined);
};
Global.bar = function()
{
closureObject.setIn = closureObject.setIn || 'set in bar';
console.log(this);
return (this !== Global ? this : undefined);
};
})(this);
var undef = (Math.ceil(Math.random()*10)%2 ? foo() : bar());
foo();//undefined --- false --- undefined --- undefined
window.foo();//Window --- true --- undefined --- window
foo.apply(this,[]);//same as window.foo
同じことがカスタムオブジェクトにも当てはまります。
function Foo(n)
{
this.name = n;
}
Foo.prototype.func = foo;//or window.foo
//other objects:
var d = new Date();
foo.apply(d,[]);//Date --- false --- undefined --- date
私の意見では、これはハッキングや落とし穴の原因となる可能性があります。さらに、呼び出しがどこから来ているのかを判断するのがかなり難しくなります。foo()
グローバルオブジェクト()から呼び出された場合、そのコンテキストは、を使用して呼び出されない限り、window.foo();
もちろんに渡されません。bar
bar
bar.apply(this,[]);
発信者のコンテキストを判断するためのカットアンドドライで安全で信頼性の高い方法が必要になる理由は単純です。これらの厄介なグローバルを回避するためにクロージャーを使用していますが、同時にいくつかの設定を行っています。イベントハンドラーとして機能する関数。
ストリクトモードを使用しない、またはグローバルを設定するのは簡単な修正ですが、ストリクトモードはそのままで、パーティーにもたらすものが気に入っています(ほとんどの場合)。これがJSの進化の仕方であると固く信じており、自分の壊れたコードに煩わされたくないので、自分が泣いているのを見つけたくありませんstrict
。それはすぐには起こらないかもしれませんが、私は自分の知識を最新の状態に保ちたいと思っています。
のMDNページとstrict
JohnResigのブログ投稿を読み、DCのビデオをかなり多く見て、彼の記事をたくさん読みましたが、上記の動作の明確な説明は見つかりませんでした。私はECMAScript標準全体を読んでいません(男の子、それはとても乾燥しているので、サハラ砂漠を排水する可能性があります)が、おそらくここの誰かが私を正しい方向に向けて、これをよりよく理解するのを助けることができます。