變數提升 先說三句總結性的話: let 的「創建」過程被提升了,但是初始化沒有提升。 var 的「創建」和「初始化」都被提升了。 function 的「創建」「初始化」和「賦值」都被提升了。 所以,我們要註意,這三種變數提升,含義是不同的。 變數提升的規律 在進入一個執行上下文後,先把 var 和 ...
變數提升
先說三句總結性的話:
let 的「創建」過程被提升了,但是初始化沒有提升。
var 的「創建」和「初始化」都被提升了。
function 的「創建」「初始化」和「賦值」都被提升了。
所以,我們要註意,這三種變數提升,含義是不同的。
變數提升的規律
在進入一個執行上下文後,先把 var 和 function 聲明的變數前置,再去順序執行代碼。
PS:作用域分為全局作用域和函數作用域,用var聲明的變數,只在自己所在的所用域有效。
我們舉例來看看下麵的代碼。
代碼 1:
console.log(fn);
var fn = 1;
function fn() {
}
console.log(fn);
相當於:
var fn = undefined;
function fn() {
}
console.log(fn);
fn = 1;
console.log(fn);
列印結果:
代碼 2:
console.log(i);
for (var i = 0; i < 3; i++) {
console.log(i)
}
相當於:
var i = undefined;
console.log(i);
for (i = 0; i < 3; i++) {
console.log(i);
}
列印結果:
代碼 3:
var a = 1;
function fn() {
a = 2;
console.log(a)
var a = 3;
console.log(a)
}
fn();
console.log(a);
相當於:
var a = undefined;
function fn() {
var a
a = 2
console.log(a)
a = 3
console.log(a)
};
a = 1;
fn();
console.log(a);
列印結果:
聲明時的重名問題
假設a
被聲明為變數,緊接著a
又被聲明為函數,原則是:聲明會被覆蓋(先來後到,就近原則)。
PS:
如果
a
已經有值,再用 var 聲明是無效的。如果
a
已經有值,緊接著又被賦值,則賦值會被覆蓋。
舉例1:
var fn; //fn被聲明為變數
function fn() {// fn被聲明為function,就近原則
}
console.log(fn); //列印結果:function fn(){}
舉例2:
function fn() {} //fn被聲明為function,且此時fn已經被賦值,這個值就是function的對象
var fn; //fn已經在上一行被聲明且已經有值, 再 var 無效,並不會重置為 undefined
console.log(fn) //列印結果:function fn(){}
既然再var無效,但是再function,是有效的:
function fn() {} //fn被聲明為function,且此時fn已經有值,這個值就是function的對象
function fn() { //此時fn被重覆賦值,會覆蓋上一行的值
console.log('smyhvae');
}
console.log(fn)
列印結果:
函數作用域中的變數提升(兩點提醒)
提醒1:
在函數作用域也有聲明提前的特性:
使用var關鍵字聲明的變數,是在函數作用域內有效,而且會在函數中所有的代碼執行之前被聲明
函數聲明也會在函數中所有的代碼執行之前執行
因此,在函數中,沒有var聲明的變數都會成為全局變數,而且並不會提前聲明。
舉例1:
var a = 1;
function foo() {
console.log(a);
a = 2; // 此處的a相當於window.a
}
foo();
console.log(a); //列印結果是2
上方代碼中,foo()的列印結果是1
。如果去掉第一行代碼,列印結果是Uncaught ReferenceError: a is not defined
提醒2:定義形參就相當於在函數作用域中聲明瞭變數。
function fun6(e) {
console.log(e);
}
fun6(); //列印結果為 undefined
fun6(123);//列印結果為123
其他題目
var a = 1;
if (a > 0) {
console.log(a);
var a = 2;
}
console.log(a);
列印結果:
1
2
上方代碼中,不存在塊級作用域的概念。if語句中用var定義的變數,仍然是全局變數。
順便延伸一下,用let定義的變數,是在塊級作用域內有效。