js-作用域及作用域鏈

作用域

任何編程語言都有作用域的概念,簡單來說,作用域就是變量與函數的可訪問範圍,即作用域控制着變量與函數的可見性和生命週期。

es6之前靠函數來形成的,,也就是說一個函數的變量在函數外不可以訪問。

  1. es6之前沒有let,從es6開始定義變量可以用let
  2. es6之前只有全局作用域和局部作用域,從es6之後添加了塊級作用域({}範圍內的作用域)
  3. es6新增了塊級作用域,但通過let定義的變量都是局部變量

全局作用域

任何地方都能訪問到的對象擁有全局作用域。

1、函數外面定義的變量擁有全局作用域

var a=1
function fn(){
  var b=4
}
console.log(a) // 1
console.log(b) // 報錯error

2、未定義直接賦值的變量自動聲明爲擁有全局作用域

var a=1
function fn(){
   b=4
}
console.log(a) // 1
console.log(b) // 4

3、window對象的屬性擁有全局作用

局部作用域

局部作用域一般只在固定的代碼片段內可訪問到,最常見的例如函數內部,所以在一些地方會把這種作用域稱爲函數作用域。

var a=1
function fn(){
  var b=4
}
console.log(a) // 1
console.log(b) // 報錯error

 上面代碼中b就是局部作用域,只能在函數內部使用

es6的塊級作用域

es5只有全局作用域和函數作用域(局部作用域),沒有塊級作用域,會帶來下面問題:

1、變量提升導致內層變量可能會覆蓋外層的變量

var a=1
function fn(){
 console.log(a)
 if(true){
  var a=6
 }   
}
fn() // undefined

2、用來計數的循環變量泄漏爲全局變量 

for(var i=0;i<10;i++){
 console.log(i)
}
console.log(i) // 10

ES6引入了塊級作用域,明確允許在塊級作用域中聲明函數,let和const命令都涉及塊級作用域。

塊級作用域允許聲明函數只在使用大括號的情況下成立,如果未使用大括號,會報錯。

作用域鏈

es6作用域鏈

  1. 全局作用域又稱爲0級作用域
  2. 定義函數或者代碼塊都會開啓作用域就是1級/2級/3級/...作用域
  3. javaScript會將這些作用域鏈接在一起形成一個鏈條,這個鏈條就是作用域鏈

                  0————>1————>2————>3————>4...

      4. 除0級作用域以外,當前作用域級別等於上一級+1

變量在作用域鏈的查找規則

  1. 現在當前找,找到就使用當前作用域找到的
  2. 如果當前作用域沒有找到,就去上一級作用域中查找
  3. 以此類推知道0級爲止,如果0級作用域還沒有找到,就會報錯

閉包

提到作用域就不得不提到閉包,簡單來講,閉包外部函數能夠讀取內部函數的變量。

優點:閉包可以形成獨立的空間,永久的保存局部變量。

缺點:保存中間值的狀態缺點是容易造成內存泄漏,因爲閉包中的局部變量永遠不會被回收

function f1(){
  var n=999;
  nAdd=function(){
    n+=1
  } 
  function f2(){
    console.log(n)
  } 
  return f2
}
var result=f1()
result() //999
nAdd()  //執行n+=1
result() //1000

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章