すべての関数が独自のコンテキストを作成し、独自のローカル変数やものを持つことができることを知っています。
したがってvar a = [5]
、最上位の関数コンテキストのコンテキストで を記述すると、記述する可能性のある新しいネストされた関数のコンテキストで使用可能になり、アクセスできるようになると想定しています。
そして、これはおそらく「文書化されていない」「予期しない」動作に遭遇する場所です。
op の 1at の例
function bar(){
if(!a) {
var a = [1,2];
}
console.log(a);
}
>> 1,2
1,2 のローカル値を返すようにします。ここで、bar関数コンテキストのif条件がホスト関数変数aをundefinedとして扱っていることがわかります。そのため、 !aをtrueに否定しています。
何故ですか?コメンテーターは巻き上げを主張します。しかし、何の巻き上げ?唯一の違いは条件付き引数にある同じ関数の 2 つのバージョンの最終結果または動作における巻き上げ原理の干渉はまったくありません。
巻き上げ!何の巻き上げ?「ホイスト」の場合 - !a操作は間違いなくfalseを返す必要があります。これは、ホストのすべての下位コンテキスト関数にアクセス可能な上位コンテキストで、 a が真の値で既に定義されているためです。でも全く逆
if(!a [false] ) したがって、条件付きリターンからtrueの結果として、var キーを使用して、同じ名前の変数の新しい宣言の実行を許可しています。より高い範囲で。
そして、そうすべきではありません。しかし、そうすべきです。
条件付きの if 引数を否定せずに同じことを試みると、次のようにエラーと代入の失敗が発生します。
function bar(){
if(a) {
var a = [1,2];
}
console.log(a);
}
>> undefined
[!if(!!a) を使用する場合と同じ] 値 [1,2] を持つ新しいローカル 'a' 変数を作成できるように、a が true かどうかを尋ねていること以外は何も変更していません。
何が起こっている?!続行するためにa引数がtrueであることが明示的に必要なif条件は、関数bar
のローカル コンテキストを検索して「下に登る」ことです。
何らかの理由で、ホスト関数の変数を再宣言し、ローカル コンテキストで同じ名前の新しい変数に初期化して値を割り当てることを拒否する試みとして処理されます。これは、ホスト変数を参照する条件式が宣言してローカル a に値を割り当てることを拒否しているため、混乱を招きます。
ただし、コンソール ログでは、ローカル変数 a が返されており、undefinedです。
これは予想外です。矛盾している; 反抗的だが一見正しい!ローカルa変数は初期化されましたが、最初は正しく値を取得できなかったため、正しいです。より高いコンテキストから 1 つを再宣言しようとしましたが、許可されませんでした。
唯一の良い点は、動作がブラウザー間で統一されているように見えることです。