
面試官:跟我說說你對作用域和作用域鏈的理解吧,
我:,,,💥

作用域
作用域就是代碼的執行環境,全域執行環境就是全域作用域,函式的執行環境就是私有作用域,它們都是堆疊記憶體,執行環境定義了變數或函式有權訪問的其他資料,決定了它們各自的行為,每個執行環境都有一個與之關聯的變數物件,環境中定義的所有變數和函式都保存在這個物件中,雖然我們撰寫的代碼無法訪問這個物件,但決議器在處理資料時會在后臺使用它,
-
全域作用域最外層函式和最外層函式外面定義的變數擁有全域作用域- 所有
未定義直接賦值的變數自動宣告為全域作用域 - 所有
window物件的屬性擁有全域作用域 - 全域作用域有很大的弊端,過多的全域作用域變數會
污染全域命名空間,容易引起命名沖突,
-
函式作用域- 函式作用域宣告在函式內部的變數,一般只有固定的代碼片段可以訪問到
- 作用域是分層的,
內層作用域可以訪問外層作用域,反之不行
-
塊級作用域
- 使用ES6中新增的let和const指令可以宣告塊級作用域,塊級作用域可以在函式中創建也可以在一個代碼塊中的創建(由{ }包裹的代碼片段)
- let和const宣告的變數不會有變數提升,也不可以重復宣告
- 在回圈中比較適合系結塊級作用域,這樣就可以把宣告的計數器變數限制在回圈內部,
作用域鏈
在當前作用域中查找所需變數,但是
該作用域沒有這個變數,那這個變數就是自由變數,如果在自己作用域找不到該變數就去父級作用域查找,依次向上級作用域查找,直到訪問到window物件就被終止,這一層層的關系就是作用域鏈,作用域鏈的作用是保證對執行環境有權訪問的所有變數和函式的有序訪問,通過作用域鏈,可以訪問到外層環境的變數和函式,作用域鏈的本質上是一個指向變數物件的指標串列,變數物件是一個包含了執行環境中所有變數和函式的物件,作用域鏈的前端始終都是當前執行背景關系的變數物件,全域執行背景關系的變數物件(也就是全域物件)始終是作用域鏈的最后一個物件,
總結
1.作用域鏈存盤的就是執行背景關系的集合
2.當前作用域中沒有使用未在在作用域定義的變數時,會沿著作用域鏈向上找,
代碼理解
var z = 1
//1.tim 定義 tim.[[scope]] = GO:{z:1,tim:[Function: tim]}
function tim(){
//3.cope定義 cope.[[scope]] = tim.[[scope]] = tim(AO):{cope:[Function: cope],y:undefined}=>GO
function cope(){
var x= 2;
// 6.cope(AO)上沒有y屬性,就會沿著作用域鏈往上找,一直沒有就會掛載在GO上
y=3
}
//4.tim(AO):{cope:[Function: cope],y:4}
var y = 4
//5.cope.[[scope]] = cope(AO):{x:undefined}=>tim(AO)=>GO
cope()
//7.tim(AO):{cope:[Function: cope],y:4}
console.log(y) // 3
}
//2.tim 執行 tim.[[scope]] = tim(AO):{cope:[Function: cope],y:undefined}=>GO:{z:1,tim:[Function: tim]}
tim()

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/290321.html
標籤:其他
上一篇:從家里到阿里,學弟求職的一年
下一篇:html的語意化
