-
作用域是根據(jù)名稱查找變量的一套規(guī)則。
- 聊到js的作用域,就不得不聊到js中的作用域鏈。作用域鏈的用途是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問,本質(zhì)是一個指向變量對象的指針列表,那是什么又是變量對象?
- 這里要引入一個極為重要的概念:執(zhí)行環(huán)境(execution context)也稱執(zhí)行上下文,執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù),每個執(zhí)行環(huán)境都有一個與之關(guān)聯(lián)的變量對象,環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中。
- js中有三種執(zhí)行環(huán)境,只討論兩種,一種是全局執(zhí)行環(huán)境,一種是函數(shù)執(zhí)行環(huán)境,每個函數(shù)都有自己的執(zhí)行環(huán)境,和一個關(guān)聯(lián)的變量對象(局部環(huán)境中的變量對象只會在函數(shù)執(zhí)行的過程中存在,而全局變量對象始終存在),創(chuàng)建函數(shù)時,會創(chuàng)建一個預先包含全局變量對象的作用域鏈,保存在函數(shù)的一個內(nèi)部屬性[[scope]]中,當某個函數(shù)第一次被調(diào)用時,會創(chuàng)建一個執(zhí)行環(huán)境,通過復制函數(shù)的[[scope]]屬性中的對象構(gòu)建起執(zhí)行環(huán)境的作用域鏈,然后又有一個活動對象(充當變量對象使用)被創(chuàng)建并被推進執(zhí)行環(huán)境作用域鏈的前端。
- 對于嵌套函數(shù)還有閉包而言,內(nèi)部函數(shù)的作用域鏈就是這樣是通過復制上一層函數(shù)的作用域鏈來構(gòu)建的,然后,用this,arguments和其他命名參數(shù)的值來初始化函數(shù)的活動對象,然后把這個對象推至當前執(zhí)行環(huán)境的作用域鏈的前端,這樣這條函數(shù)作用域鏈就包含了自己本地的活動對象,上一層函數(shù)的變量對象,一直向上到全局環(huán)境的變量對象
- 這也解釋了閉包的原理,閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù),在一個函數(shù)內(nèi)部創(chuàng)建另一個函數(shù)是創(chuàng)建閉包的常見方式。函數(shù)內(nèi)部的變量可以訪問包含函數(shù)的變量。
(如果在當前作用域中沒有查到值,就會向上級作用域去查,直到查到全局作用域,這么一個查找過程形成的鏈條就叫做作用域鏈)
總結(jié):
- 所謂的作用域鏈就是在函數(shù)的當前執(zhí)行環(huán)境中中查找變量,如果查找不到,就會向上一級函數(shù)中的執(zhí)行環(huán)境中查找,一直引申到全局執(zhí)行環(huán)境,這樣一個向上查找的過程就形成了作用鏈
- 再展開一點來講的話就是,每創(chuàng)建一個函數(shù)都會創(chuàng)建相應的執(zhí)行環(huán)境,這個執(zhí)行環(huán)境又有一個與之關(guān)聯(lián)的變量對象,函數(shù)中定義的變量和內(nèi)部函數(shù),都是保存在這個變量對象里面的,然后作用域鏈就是一個指向變量對象的指針列表,這個列表里面,最開頭指針指向的就是當前函數(shù)的變量對象,然后一直向后指向的是上一級函數(shù)的變量對象,然后再上一級別函數(shù)的變量對象,一直到全局執(zhí)行環(huán)境的變量對象,如果在當前的變量對象中查找不到變量,就只能去查找上一 級函數(shù)的變量 對象。