中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

好程序員web前端帶你了解JS的作用域鏈

發布時間:2020-08-09 09:28:08 來源:ITPUB博客 閱讀:139 作者:好程序員IT 欄目:web開發

好程序員 web前端帶 你了解 JS的作用域鏈, 我們都知道 js 是一個基于對象的語言,系統內置各種對象。

 

window 作為一個天然存在的全局對象,它承擔了所有全局資源的存儲。

 

我們使用的任何全局變量,都是 window 下的。也就是說,在 js 中,實際上沒有任何對象、方法是可以獨立的,它們必須依賴于某個對象才可以被訪問或執行。

 

就像 alert() ,它的完整寫法是 window.alert()

parseInt(),  完整寫法是 window.parseInt()

 

所有放在 window 對象下的資源,訪問時可以默認省略 window

 

但有一種情況非常特殊,例如函數中的局部變量:

function  Person(){

        var  name =  “abc” ;

}

當我們試圖訪問這個 name 屬性時

console.log(newPerson().name); 

結果是 undefined

我們只能在函數內部訪問:

function  Person(){

        var  name =  “abc”;

        console .log(name);

}

這種屬性,在構造函數中,也被稱為私有屬性,我們必須提供一種對外公開的方法才可以被外界訪問。例如:

function  Person(){

        var  name =  “abc” ;

        this .getName =  function (){

        return name;

}

this .setName=  function (_name){

       name = _name;

}

}

這是一個典型的作用域問題 似乎我們每個人都知道。

 

但這似乎也違反了我們的一個常識:那就是在 js 中,所有資源都必須依賴對象才能存在,不可獨立使用。比如說:

function  aaa(){

        function  bbb(){  }

       bbb();

}

這段代碼看上去并沒有錯,但是請問 bbb 這個函數為什么可以獨立存在呢?如果我們把它換成這樣:

function  aaa(){

        function  bbb(){  }

        window .bbb();

}

結果是運行錯誤!

 

那如果換成這樣呢?

function  aaa(){

        function  bbb(){  }

        this .bbb();

}

結果還是運行錯誤!

 

那么我們不禁要發問了, bbb 這個函數到底是屬于哪個對象的?

 

當我們在調用一個函數的時候,瀏覽器會為這個函數的執行開辟一塊內存區域用來存儲這個方法在執行的臨時數據。而對象作為 js 的基本存儲單位,因此,臨時數據實際上都被保存到了一個對象當中,這個對象,就是我們平時所說的 執行上下文環境

 

當我們調用 aaa 函數時,例如 window.aaa()

瀏覽器會為這一次函數的執行,創建一個執行上下文環境對象,我們暫時給它起個名字,叫做 contextAAA 吧,當然它是臨時的,因為函數執行完它也就消失了。

 

那我們的代碼實際上會變成這樣:

function  aaa(){

        function  bbb(){   }

        contextAAA .bbb();

}

盡管 contextAAA 對象是看不見的,但它確實存在。

 

而當我們執行 bbb 函數時,瀏覽器會再次為這一次函數調用創建一個臨時的執行上下文環境,我們暫且叫它 contextBBB

那么 contextAAA  contextBBB以及window 之間會形成鏈條關系,

舉個例子來說明吧

var  num = 888;

function  aaa(){

        var  num = 100;

        function  bbb(){

        var  num= 200;

        console .log(num);

}

bbb();

}

aaa();

那么 contextAAA  如下:

contextAAA = {

       num  100,

       bbb :  function (){ … },

       parentContext:  window // 父級上下文對象

}

那么 contextBBB 如下:

contextBBB = {

       num : 200,

       parentContext: contextAAA // 父級上下文對象

}

因此我們發現,在父級上下文對象中,我們沒有辦法訪問到子級上下對象,這是一個單向鏈表,這就是全局不能訪問局部的原因。

 

bbb 函數中打印出的 num 應該是多少呢?這取決在上下文對象中的查找順序,順序大概是這樣的:

首先在當前上下文對象 contextBBB 中,找一下有沒有 num 變量,找到就直接打印。以我們目前的代碼看,結果應該是 200

我們把代碼改造一下:

var  num= 888;

function  aaa(){

        var  num = 100;

        function  bbb(){

        console .log(num);

}

bbb();

}

aaa();

由于這次在 contextBBB 對象中找不到 num 變量了,因此它會從父級上下文對象中查找,也就是 contextAAA 里面的 num ,因此打印的結果是 100;

我們再把代碼改造一下

var  num= 888;

function  aaa(){

        function  bbb(){

        console .log(num);

}

bbb();

}

aaa();

由于這次連 contextAAA 對象里也找不到了,會再次向它的父級上下文對象,也就是 window 查找,因此打印結果是 888

 

contextAAA contextBBB 的父子關系,在你寫代碼的一刻就決定了,這就是作用域。

function  aaa(){

        var  num = 10;

        function  bbb(){   console .log(num);  }

}

而代碼執行時,產生的上下文對象,是鏈表的關系。這就是我們所說的作用域鏈,它的原理跟原型鏈是一樣的。

好程序員web前端帶你了解JS的作用域鏈

理解了這一點,也能弄明白閉包的原理。

function  aaa(){

       var  num = 10;

        return   function bbb(){   console .log(num);  }

}

aaa( )( )

盡管 bbb函數通過return在全局范圍被執行了,但作用域的鏈表關系并沒有發生改變,因此,bbb函數依然可以訪問num這個局部變量。


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

辽中县| 昌黎县| 章丘市| 汝南县| 灯塔市| 安平县| 安多县| 富民县| 本溪市| 武陟县| 大理市| 车致| 朔州市| 嵩明县| 雅江县| 台北市| 永新县| 如皋市| 咸宁市| 西峡县| 兴义市| 醴陵市| 阿尔山市| 平阳县| 梁平县| 浠水县| 岳阳市| 本溪市| 玉溪市| 太仆寺旗| 富平县| 琼海市| 泊头市| 商水县| 噶尔县| 临沂市| 托克逊县| 义马市| 色达县| 元谋县| 长岭县|