Javascript用關(guān)鍵字 var 聲明的變量有函數(shù)作用域和全局作用域兩種
Javascript用關(guān)鍵字 let 聲明的變量有塊級作用域
用var聲明的變量有變量提升,let沒有變量提升
1. var-函數(shù)作用域
1.1 如果一個變量在函數(shù)體內(nèi)部申明债鸡,則該變量的作用域為整個函數(shù)體江滨,在函數(shù)體外不可引用該變量
function foo() {
var x = 1;
x = x + 1;
}
x = x + 2; // ReferenceError! 無法在函數(shù)體外引用變量x
1.2 不同函數(shù)內(nèi)部的同名變量互相獨(dú)立,互不影響.
function foo() {
var x = 1; //僅在這個函數(shù)體內(nèi)有作用
x = x + 1;
}
function bar() {
var x = 'A'; //僅在這個函數(shù)體內(nèi)有作用
x = x + 'B';
}
1.3 對于嵌套函數(shù)厌均,內(nèi)部函數(shù)可以訪問外部函數(shù)定義的變量唬滑,外部函數(shù)不能訪問內(nèi)部函數(shù)的變量。
function foo() {
var x = 1; //外部函數(shù)的變量 x
function bar() {
var y = x + 1; // bar可以訪問foo的變量x!
}
var z = y + 1; // ReferenceError! foo不可以訪問bar的變量y!
}
function foo() {
var x = 1;
function bar() {
var x = 'A';
console.log('x in bar() = ' + x); // 'A'
}
console.log('x in foo() = ' + x); // 1
bar();
}
foo(); //x in foo() = 1 x in bar() = A
說明:JavaScript的函數(shù)在查找變量時從自身函數(shù)定義開始棺弊,從“內(nèi)”向“外”查找晶密。如果內(nèi)部函數(shù)定義了與外部函數(shù)重名的變量,則內(nèi)部函數(shù)的變量將“屏蔽”外部函數(shù)的變量
1.4 變量提升
JavaScript的函數(shù)定義有個特點模她,它會先掃描整個函數(shù)體的語句稻艰,把所有申明的變量“提升”到函數(shù)頂部
function foo() {
var x = 'Hello, ' + y;
console.log(x); //輸出 hello undefined
var y = 'Bob';
}
foo();
實際上,JavaScript引擎看到的代碼相當(dāng)于
function foo() {
var y; // 提升變量y的申明,此時y為undefined
var x = 'Hello, ' + y;
console.log(x);
y = 'Bob';
}
由于JavaScript的這一怪異的“特性”缝驳,我們在函數(shù)內(nèi)部定義變量時连锯,請嚴(yán)格遵守在函數(shù)內(nèi)部首先申明所有變量這一規(guī)則
2. var-全局作用域
不在任何函數(shù)內(nèi)定義的變量就具有全局作用域
var funcs = []
for (var i = 0; i < 10; i++) { //這里在for循環(huán)里定義的 var i 是全局作用域
funcs.push(function() { console.log(i) })
}
funcs.forEach(function(func) {
func() //結(jié)果是輸出10 十次。
})
分析:每次for循環(huán)數(shù)組里面加一個函數(shù).執(zhí)行完循環(huán)用狱,i=10,并且最后funcs數(shù)組里面放了10個函數(shù)运怖。
funcs.forEach數(shù)組調(diào)用這個方法,回調(diào)函數(shù)的參數(shù)func就是數(shù)組里面的每個元素夏伊,對數(shù)組里面的每個元素執(zhí)行func() 摇展,相當(dāng)于執(zhí)行數(shù)組元素的函數(shù)體console.log(i) ,所以所有的執(zhí)行都是輸出10
3. let塊級作用域
ES6引入了新的關(guān)鍵字let溺忧,用let替代var可以申明一個塊級作用域的變量
function foo() {
var sum = 0;
for (let i=0; i<100; i++) {
sum += i;
}
i += 1; // SyntaxError:僅在for循環(huán)體內(nèi)有作用
}
對比全局作用域的例子
const funcs = []
for (let i = 0; i < 10; i++) {
funcs.push(function() {
console.log(i)
})
}
funcs.forEach(func => func()) //輸出0咏连,1,2鲁森,3祟滴,4,5歌溉,6垄懂,7骑晶,8,9