函式作用域和作用域鏈

2022-03-27 23:59:37 字數 2628 閱讀 9634

所謂作用域就是:變數在宣告它們的函式體以及這個函式體巢狀的任意函式體內都是有定義的。

function scope()

while(1)

!function ()();

console.log(

foo,//global

a, // i'm if

b, // i'm while

c // c is not defined

);}scope();

但是,在js中有一種特殊情況:

如果乙個變數沒有使用var宣告,window便擁有了該屬性,因此這個變數的作用域不屬於某乙個函式體,而是window物件。

function varscope()

varscope();

console.log(window.foo); //i'm in function

所謂作用域鏈就是:乙個函式體中巢狀了多層函式體,並在不同的函式體中定義了同一變數, 當其中乙個函式訪問這個變數時,便會形成一條作用域鏈。

foo = "window";

function first()

function third()

second(); //second

third(); //first

}first();

當執行second時,js引擎會將second的作用域放置鍊錶的頭部,其次是first的作用域,最後是window物件,於是會形成如下作用域鏈:

second->first->window,  此時,js引擎沿著該作用域鏈查詢變數foo, 查到的是 second

當執行third時,third形成的作用域鏈:third->first->window, 因此查到的是:frist

with 和 catch 語句主要用來臨時擴充套件作用域鏈, 將語句中傳遞的變數物件新增到作用域的頭部。語句結束後,原作用域鏈恢復正常。

//with語句

foo = "window";

function first()

function third(obj)

console.log(foo); //first

}var obj = ;

third(obj);

}first();

//catch語句

var e = new error('a');

try catch (e)

在執行third()時,傳遞了乙個obj物件,obj 中有屬性foo, 在執行with語句時,js引擎將obj放置在了原鍊錶的頭部,於是形成的作用域鏈如下:

obj->third->first->window, 此時查詢到的foo就是obj中的foo,因此輸出的是 obj

而在with之前和之後,都是沿著原來的鍊錶進行查詢,從而說明在with語句結束後,作用域鏈已恢復正常。

在乙個函式中,this總是指向當前函式的所有者物件,this

總是在執行時才能確定其具體的指向, 也才能知道它的呼叫物件。

window.name = "window";

function f()

f();//window

var obj = ;

f.call(obj); //obj

在執行f()時,此時f()的呼叫者是window物件,因此輸出 window 

f.call(obj) 是把f()放在obj物件上執行,相當於obj.f(),此時f 中的this就是obj,所以輸出的是 obj

demo1:

var foo = "window";

var obj = ;

}};var f = obj.getfoo();

f(); //window

demo2:

var foo = "window";

var obj = ;

}};var f = obj.getfoo();

f(); //obj

// demo1:

//執行var f = obj.getfoo()返回的是乙個匿名函式,相當於:

var f = function()

// f() 相當於window.f(), 因此f中的this指向的是window物件,this.foo相當於window.foo, 所以f()返回"window"

// demo2:

// 執行var f = obj.getfoo() 同樣返回匿名函式,即:

var f = function()

// 唯一不同的是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"

如對結果有疑惑,歡迎討論!

原創發布 @一畫素  2015.12

作用域和作用域鏈

全域性作用域 全域性的變數執行環境 函式作用域 函式內部的變數執行環境 每個函式都有自己的執行環境,當執行流進入乙個函式時,函式的環境就會被推入乙個環境棧中。函式執行之後,棧將環境彈出,把控制權返回給之前的執行環境。全域性作用域只要頁面不解除安裝,就一直存在,不釋放。函式每次在呼叫時,都會形成乙個作...

作用域和作用域鏈

var a 10 function f1 x,y f1 console.log b 此時b輸出5,因為b 5為隱式的全域性變數 在函式外面使用var 宣告的變數都是全域性變數,作用範圍是程式執行的地方.全域性作用域 函式除外 函式的形參是區域性變數 在函式內部,不使用var 定義的變數,叫隱式全域性...

作用域和作用域鏈

執行環境定義了變數和函式有權訪問的其他資料,決定了他們各自的行為。每個執行環境都有與之對應的變數物件 variable object 儲存著該環境中定義的所有變數和函式。我們無法通過 來訪問變數物件,但是解析器在處理資料時會在後台使用到它。執行環境有全域性執行環境 也稱全域性環境 和函式執行環境之分...