JS-作用域

徐海東發表於2019-02-18

全域性變數,個人理解全域性變數就是全域性物件window的屬性

var a = 5  // 宣告一個全域性變數
console.log(window.a) // 5
複製程式碼

1.變數作用域

javaScript的全域性變數的作用域,顧名思義作用域就是全域性,而函式的引數跟區域性變數的作用域在函式體內。

如果兩個變數重名,一個變數是全域性變數,一個是區域性變數,優先順序是 區域性變數>全域性變數

var a = 1    // 宣告全域性變數
function fuc() {
    var a = 2 // 區域性變數
    return a
}
console.log(fuc()) // 2複製程式碼

如果在函式內宣告變數沒有帶var,會被當作全域性變數,也叫隱式宣告

function fuc() {
    var a = 2 // 區域性變數
    return a
}
console.log(a) // a is not defined複製程式碼

function fuc() {
    a = 2 //  沒有var,此時a是全域性變數
    return a
}
console.log(a) // 2複製程式碼

2.函式作用域

javaScript變數的作用域,與java等語言不同的是,在變數宣告的程式碼塊之外是不可見的,簡稱“塊級作用域”

function fuc(){
    console.log(num)  // 輸出未定義的變數 會報錯
}
fuc() // num is not defined複製程式碼

function fuc(){
    console.log(num)  // 不報錯, 輸出undefined,因為num在函式體內有定義
    var num = 5
    console.log(num) // 5
}
fuc() 
//由於變數提升,上面程式碼等價於
function fuc(){
    var num
    console.log(num)  // undefined
    num = 5
    console.log(num) // 5
}
fuc() 
複製程式碼

3.作用域鏈

javaScript的函式是允許巢狀的,就是在一個函式內部宣告另一個函式,程式碼如下

function A(){
    var num = 5
    function B() {
        var b = 2
    }
}
複製程式碼

執行A函式的時候,會建立A函式的作用域,B函式在建立的時候會引用A的作用域

JS-作用域

執行B函式的時候會引用函式A的作用域,由所謂的函式作用域的巢狀形成了函式作用域鏈。

在自身如果找不到該變數的時候,就會沿著作用域向上查詢,直至在全域性作用域找不到時丟擲錯誤

作用域題目

  • js內部作用域可以訪問外部,但外部不能訪問內部

var a = 10
function aaa () { 
 alert(a)  // 呼叫順序3,內部沒有a變數,沿著作用域鏈向上尋找,在找到全域性變數a =10
} 
function bbb () {
    var a = 20
    aaa()  // 呼叫順序2
} 
bbb()  // 呼叫順序1  結果為10複製程式碼
  • 不用var定義變數,會預設為全域性變數

function aaa(){
      var a=b=10    
}
 aaa()
 alert(a) // 報錯
 alert(b) // 10

//上面aaa()的程式碼等價於下面
var b = 10
function aaa() {
    var a = b
}複製程式碼

  • 尋找變數是就近原則,沿著作用域鏈往上找,變數的宣告會被提升至頂部,賦值會留在原地

function aaa () {
  alert(a)
  var a = 20
}
aaa() // undefined  此題與上面第二點的例子一樣複製程式碼

  • 同名的全域性變數跟區域性變數,區域性變數優先順序大於全域性

var a = 10
function aaa () {
  alert(a)
  var a = 20
}
aaa() //結果為:undefined

//此程式碼等價於
var a = 10
function aaa () {
    var a
    alert(a)  //undefined
    a = 20
}
aaa() //結果為:undefined複製程式碼

  • 如果形參與區域性變數同名時,優先順序一樣

var a = 10
function aaa (a) { // 函式傳入形參 a
  alert(a)
  var a = 20
}
aaa(a) // 結果為: 10複製程式碼

var a = 1
var a       // 這裡的var a 是一個重複定義,變數只有定義後未賦值才會輸出undefined,
               這裡JS引擎對重複定義的規定是:以最近的變數賦值作為變數在執行時的值
               所以var a相當於無效
console.log(a) // 1
複製程式碼

  • 變數修改的時候,另一個變數會跟著變化,但是重新定義時,另一個不跟隨變化

var a=[1,2,3]
var b = a
b.push(4)
alert(a) // 結果為[1,2,3,4] 當b改變的時候a也發生了改變  

當b重新被賦值的時候 a不會改變.示例:
var a = [1,2,3]
var b = a
b = [1,2,3,4]
alert(a) // 結果為 [1,2,3]
複製程式碼


相關文章