javascript 作用域和 this 關鍵字

發表於2016-02-27

在javascript中存在著this和scope兩個概念,如果不細心瞭解,還真搞不清楚這兩個概念,今天我們就來詳細瞭解一下this和scope的區別以及它們的作用,最後會附上code以加深理解。

一、作用域(scope)

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

(1)scope函式中定義的foo變數,除過自身可以訪問以外,還可以在if語句、while語句和內嵌的匿名函式中訪問。 因此,foo的作用域就是scope函式體。

(2)在javascript中,if、while、for 等程式碼塊不能形成獨立的作用域。因此,javascript中沒有塊級作用域,只有函式作用域。

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

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

二、作用域鏈(scope chain)

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

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

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

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

特殊情況:with語句

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

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

obj->third->first->window, 此時查詢到的foo就是obj中的foo,因此輸出的是:”obj”, 而在with之前和之後,都是沿著原來的連結串列進行查詢,從而說明,在with語句結束後,作用域鏈已恢復正常。

三、this 關鍵字

     在一個函式中,this總是指向當前函式的所有者物件,this總是在執行時才能確定其具體的指向, 也才能知道它的呼叫物件。

     這句話總結了關於this的一切,切記,切記,切記!(ps:重要的事情說三遍!)

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

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

四、實戰應用

code1:

code2:

code1和code2是對this和scope最好的總結,如果對於執行結果有疑惑,歡迎討論!

程式碼解析:

相關文章