ホームページ > 記事 > ウェブフロントエンド > JS Core シリーズ: 関数の範囲に関する簡単な説明
1. スコープ
いわゆるスコープは、変数が宣言されている関数本体と、この関数本体がネストされている関数本体で定義されます。
function scope(){ var foo = "global"; if(window.getComputedStyle){ var a = "I'm if"; console.log("if:"+foo); //if:global } while(1){ var b = "I'm while"; console.log("while:"+foo);//while:global break; } !function (){ var c = "I'm function"; console.log("function:"+foo);//function:global }(); console.log( foo,//global a, // I'm if b, // I'm while c // c is not defined ); } scope();
(1)scope 関数で定義された foo 変数は、それ自体でアクセスできるだけでなく、if ステートメント、while ステートメント、および埋め込まれた匿名関数からもアクセスできます。 したがって、foo のスコープはスコープ関数本体になります。
(2) JavaScript では、if、while、for などのコード ブロックは独立したスコープを形成できません。したがって、JavaScript にはブロックレベルのスコープはなく、関数スコープのみが存在します。
ただし、JS には特殊なケースがあります:
変数が var で宣言されていない場合、ウィンドウはこの属性を持つことになるため、この変数のスコープは特定の関数本体に属さず、ウィンドウオブジェクト。
function varscope(){ foo = "I'm in function"; console.log(foo);//I'm in function } varscope(); console.log(window.foo); //I'm in function
2. スコープ チェーン
いわゆるスコープ チェーンとは、関数本体の複数の層がネストされており、同じ変数が異なる関数本体で定義されているものです。関数の一部がこの変数にアクセスすると、スコープ チェーンが形成されます。
foo = "window"; function first(){ var foo = "first"; function second(){ var foo = "second"; console.log(foo); } function third(){ console.log(foo); } second(); //second third(); //first } first();
ond の場合、JS エンジンはリンク リストの先頭に Second のスコープを配置し、続いて First のスコープ、最後に window オブジェクトを配置します。そのため、次のスコープ チェーンが形成されます:
Second-> ;first-> ウィンドウでは、この時点で、JS エンジンはスコープ チェーンに沿って変数 foo を検索し、「2 番目」を見つけます
3 番目が実行されると、3 番目によって形成されるスコープ チェーンは次のようになります: third->first- >ウィンドウなので、検索 私が得たものは次のとおりです: "frist"
特殊なケース: with ステートメント
JS の with ステートメントは、主にスコープ チェーンを一時的に拡張し、ステートメント内のオブジェクトを先頭に追加するために使用されます。範囲の。 with ステートメントが終了すると、スコープ チェーンは通常の状態に戻ります。
foo = "window"; function first(){ var foo = "first"; function second(){ var foo = "second"; console.log(foo); } function third(obj){ console.log(foo); //first with (obj){ console.log(foo); //obj } console.log(foo); //first } var obj = {foo:'obj'}; third(obj); } first();
third() を実行すると、obj オブジェクトが渡され、obj には属性 foo が付けられます。with ステートメントを実行すると、JS エンジンは元のリンク リストの先頭に obj を配置し、形成されるスコープ チェーンは次のようになります。 :
obj->third->first->window、この時点で見つかった foo は obj の foo であるため、出力は次のようになります: "obj"、with の前後は、元のリンクに沿っていますlist with ステートメントの終了後にスコープ チェーンが通常に戻ったことを示すために検索が実行されます。
3. このキーワード
関数では、thisは常に現在の関数のオーナーオブジェクトを指します。this
は実行時にのみその特定のポインターを決定でき、その後でのみ決定できます私たちはその呼び出しオブジェクトを知っています。この文はこれについてすべてを要約しています、覚えておいてください、覚えておいてください! (追記: 重要なことは 3 回言います!)
window.name = "window"; function f(){ console.log(this.name); } f();//window var obj = {name:'obj'}; f.call(obj); //obj
f() を実行するとき、この時点では f() 呼び出し元はウィンドウですオブジェクトなので、出力「window」
f.call(obj) は、obj オブジェクトに f() を配置して実行することになります。これは、obj.f() と同等です。このとき、f の this は obj、出力は "obj" です IV. 実用的なアプリケーション
code1:
var foo = "window"; var obj = { foo : "obj", getFoo : function(){ return function(){ return this.foo; }; } }; var f = obj.getFoo(); f(); //window
code2:
var foo = "window"; var obj = { foo : "obj", getFoo : function(){ var that = this; return function(){ return that.foo; }; } }; var f = obj.getFoo(); f(); //obj
code1 と code2 は、疑問がある場合に最適な要約です。実行結果については、ご相談ください。
コード分析:
code1: 执行var f = obj.getFoo()返回的是一个匿名函数,相当于: var f = function(){ return this.foo; } f() 相当于window.f(), 因此f中的this指向的是window对象,this.foo相当于window.foo, 所以f()返回"window" code2: 执行var f = obj.getFoo() 同样返回匿名函数,即: var f = function(){ return that.foo; } 唯一不同的是f中的this变成了that, 要知道that是哪个对象之前,先确定f的作用域链:f->getFoo->window 并在该链条上查找that,此时可以发现that指代的是getFoo中的this, getFoo中的this指向其运行时的调用者,从var f = obj.getFoo() 可知此时this指向的是obj对象,因此that.foo 就相当于obj.foo,所以f()返回"obj"🎜🎜