js的變量作用域是函數級的,在js里沒有類似c語言的塊級作用域。
js編程環境的頂級作用域是window對象下的范圍,稱為全局作用域,全局作用域中的變量稱為全局變量。
js中的全局變量相當于js中頂級作用域(window)的屬性。
js函數內的變量無法在函數外面訪問,在函數內卻可以訪問函數外的變量,函數內的變量稱為局部變量。
js函數可以嵌套,多個函數的層層嵌套構成了多個作用域的層層嵌套,這稱為js的作用域鏈。
js作用域鏈的變量訪問規則是:如果當前作用域內存在要訪問的變量,則使用當前作用域的變量,否則到上一層作用域內尋找,直到全局作用域,如果找不到,則該變量為未聲明。
注意,變量的聲明在代碼解析期完成,如果當前作用域的變量的聲明和賦值語句寫在變量訪問語句后面,js函數會認為當前作用域已經存在要訪問的變量不再向上級作用域查找,但是,由于變量的賦值發生的代碼運行期,訪問的到變量將是undefined。
var a = 10;
var b = 2;
var c = 10 ;
this.a = 0; // 這里的this指向的是頂級作用域(window) 所以 現在的變量a的value變為啦0
function fn () {
var c = 10;
function() {
console.log(a) // 在執行的時候他會在作用域鏈中尋找這個a,但是在這個匿名函數中的作用域中沒有這個a,它就會從在作用域鏈的下一級去找,但是下一級也沒a,只有再去作用域的下一級找a,最終在全局中找到這個變量a值為0
var c = 0;
console.log(c) //由于在這個函數作用域的最頂端就可以找到變量c所以值為0;
console.log(d) // 還是正常的去作用域鏈中查找變量d,由于咱們沒有聲明并賦值這個變量d,所以會Error
console.log(str) // 由于js中有變量提升這個功能,所以所有變量全部會提升到函數的最頂端并賦值為 undefined 由于咱們這個變量是在賦值之前使用所以會輸出undefined
var str = '我是小白'
}
}
下邊在說一下函數聲明整體提升和變量聲明提升
變量聲明提升其實是把變量生命提升到當前函數的最頂端賦值為undefined
函數聲明整體提升是把函數聲明以及函數的代碼塊全部提升到函數的最頂端
下面看一個例子
demo() // 1 因為函數聲明整體提升的原因把這個demo函數提升到啦最頂端 所以會執行 。 其實你把函數函數執行寫在函數聲明上邊或者下邊其實都是一樣的
function demo() {
console.log(1)
}
那么兩個提升到底是誰會先提升呢
var demo = 0;
function demo () {
console.log(1)
}
demo() // demo is not a function
答案是函數會先提升,所以會產生Error