JavaScript学習ノート-スコープ
7293 ワード
これらの知識点に詳しいと思います.ネット上には似たような文章がたくさんあります.間違いないです.これらの知識は全部「あなたが知らないJavaScript(上巻)」から得たものです.なぜもう一度書きますか?
一.スコープ
スコープは、変数がどこにあるか、どのように検索されるかを決定するためのルールです.
二.静的スコープ&ダイナミックスコープ
静的作用域は語法作用域とも呼ばれ、JavaScriptはこのような作用域を採用しています.これに対応するのは動的作用域です.それらの間の主な違いは、静的作用域はコードを書く時か定義する時に決められます.動的作用領域はコードを代行する時に決められます.
三.静的スコープ(品詞作用領域)
語法の作用域はその名前と同じで、語法の分析段階で決められたのです.JavaScriptコードは実行前にコンパイルが必要で、コンパイルは三つのステップに分けられます.品詞分析はコードを品詞ユニットに分解します.例えば、var a=1です.var、a、=、1、に分解されます.これらの語法ユニット 文法解析では、語法ユニットをプログラムの文法構造を表すツリーに変換します.この木を「抽象文法ツリー」と呼びます. コードは、抽象的な構文ツリーを実行可能なコードに変換する. 例:グローバルスコープ全体の変数はJavaScriptコードのどこにでもアクセスと修正できます.グローバルスコープの変数はグローバルオブジェクトの属性です.JavaScriptコードがブラウザの環境で実行されている場合、この全体のオブジェクトはwindowです.node.jsの場合、このグローバルオブジェクトはglobalです.例: です.関数のスコープ関数のスコープ内の変数はこの関数でしかアクセスできません.関数以外ではアクセスおよび変更できません.閉ループによって関数外のスコープにアクセスし、関数のスコープ内の変数を変更することができます.例: ブロック級作用領域 ブロックレベルのスコープはes 6の前に既に存在しています.try...catch.文、例:
evalとwithを使うと法の作用領域を騙すことができますが、それを推奨しない理由は:厳格モードでは、withは禁止されています. 遅い evalは安全性の問題があります. withは、いくつかの予想外の変数 を宣言する可能性がある.
まず、詐欺の方法を見てみます.試験性能
chromeブラウザコンソールにおいて:
chromeブラウザコンソールにおいて:補足説明 withについては、予想外の変数を宣言する可能性があるという点について、直接例を挙げて説明します.私の表現能力を使うと、ますます困惑するばかりです. はwithとevalを使って遅くなる原因を説明しています.概括すると、エンジンはコンパイルする時に、作用域のルックアップを最適化して、コードの運行時に対応する作用域を迅速に見つけやすくします.しかし、withとevalのコードを使って、Withとevalのコードを使って、作用領域をどのように修正しますか?だから最適化しないしかないです. 六.スコープとスコープの検索規則
スコープ間は入れ子ができます.例えば、
作用領域を検索すると、ある変数が現在のスコープで検索されます.大域的なスコープが見つからない場合は、上(または外)へ検索されます.
上記の例では、foo関数はまず自分の作用領域から検索し、見つからないなら外層の作用域を探します.つまり大域作用域を探して、大域作用域を見つけたら、まだないことが分かります.検索を停止して、異常を捨てればいいです.
このルックアッププロセスによって形成される鎖は、ロールドメインチェーンと呼ばれる.
転載先:https://juejin.im/post/5b90d18f6fb9a05ce873b874
一.スコープ
スコープは、変数がどこにあるか、どのように検索されるかを決定するためのルールです.
二.静的スコープ&ダイナミックスコープ
静的作用域は語法作用域とも呼ばれ、JavaScriptはこのような作用域を採用しています.これに対応するのは動的作用域です.それらの間の主な違いは、静的作用域はコードを書く時か定義する時に決められます.動的作用領域はコードを代行する時に決められます.
三.静的スコープ(品詞作用領域)
語法の作用域はその名前と同じで、語法の分析段階で決められたのです.JavaScriptコードは実行前にコンパイルが必要で、コンパイルは三つのステップに分けられます.
var a = 1
function foo() {
var a = 2;
bar();
}
function bar() {
console.log(a);
}
foo(); // 1
四.グローバルスコープ&関数スコープ&ブロックレベルスコープvar bar = 1;
function foo() {
console.log(bar);
}
foo(); // 1
window.foo(); // 1
window.bar; // 1
ここで注意したいのですが、letとconstを使ってグローバルスコープで変数を宣言すると、この変数は依然としてグローバル変数ですが、グローバルオブジェクトの属性ではなく、例let a = 1;
window.a; // undefined
function foo() {
console.log(a);
}
foo(); // 1
function foo() {
var bar = 1;
}
foo();
console.log(bar); // Uncaught ReferenceError: bar is not defined
注意:任意のキーワードを使用せずに直接変数を宣言すると、この変数は大域変数となります.例:function foo() {
bar = 1
}
foo();
console.log(bar); // 1
try{
throw 1;
} catch(a) {
console.log(a); // 1
}
console.log(a); // a is not defined
es 6の構文では、letおよびconstキーで宣言される変数は、現在のコードブロックにしかアクセスできません.例:{ let foo = 1; }
{ const bar = 2; }
console.log(foo); // foo is not defined
console.log(bar); // bar is not defined
五.誤魔化すevalとwithを使うと法の作用領域を騙すことができますが、それを推奨しない理由は:
まず、詐欺の方法を見てみます.
// eval
function foo(str, a) {
eval(str);
console.log(a, b);
}
var b = 2;
foo('var b = 3', 1); // 1, 3,
// with
function bar() {
var c = 2;
with(window) {
console.log(c);
}
}
var c = 1;
bar(); // 1
// eval
let a = 0;
let b = 0;
function useEval() {
console.time('useEval');
for(let i = 0; i < 10000; i += 1) {
a = eval(`${a} + ${i}`);
}
console.timeEnd('useEval');
}
function noEval() {
console.time('noEval');
for(let i = 0; i < 10000; i += 1) {
b += i;
}
console.timeEnd('noEval');
}
noEval();
useEval();
node.js中:chromeブラウザコンソールにおいて:
// with
let obj = {
a: 0,
b: 1
};
function useWith() {
console.time('useWith');
with(obj) {
for(let i = 0; i < 10000; i += 1) {
a = a + i;
}
}
console.timeEnd('useWith');
}
function noWith() {
console.time('noWith');
for(let i = 0; i < 10000; i += 1) {
obj.b = obj.b + i;
}
console.timeEnd('noWith');
}
useWith();
noWith();
node.js中:chromeブラウザコンソールにおいて:
let obj = {
a: 1
}
with(obj) {
a = 3
b = 2
}
console.log(obj); // {a: 3}
console.log(b); // 2
どうしてこのようにしてこの文章の12種類の使うべきでないJavascript文法を見に行くことができますか?スコープ間は入れ子ができます.例えば、
{
let a = 1;
{
let b = 2;
}
}
function foo() {
let c = 3;
function bar() {
let d = 4;
}
bar();
console.log(d);
}
関数fooを実行すると、エラー情報がd is not defined
に報告されます.その理由は、作用領域の検索ルールです.作用領域を検索すると、ある変数が現在のスコープで検索されます.大域的なスコープが見つからない場合は、上(または外)へ検索されます.
上記の例では、foo関数はまず自分の作用領域から検索し、見つからないなら外層の作用域を探します.つまり大域作用域を探して、大域作用域を見つけたら、まだないことが分かります.検索を停止して、異常を捨てればいいです.
このルックアッププロセスによって形成される鎖は、ロールドメインチェーンと呼ばれる.
転載先:https://juejin.im/post/5b90d18f6fb9a05ce873b874