前言
從概念的字面意義上說,"變數提升”意味著變數和函式的宣告會在物理層面移動到程式碼的最前面,但這麼說並不準確。實際上變數和函式宣告在程式碼裡的位置是不會動的,而是在編譯階段被放入記憶體中。
不多說,直接擼程式碼吧 ~~~///(^v^)\\\~~~
正文
什麼是變數提升?
javascript在被解析的時候,會有一個預解析階段,這個時候解析器會將當前上下文環境中的所有變數(不包括es6中的let和const宣告)和函式宣告提升到最前面。
先來看下面的程式碼:
'use strict';
console.log(a); // undefined
var a = 1;
console.log(a); // 1
複製程式碼
那麼在程式碼被解析的時候,就是這樣:
'use strict';
var a;
console.log(a); // undefined
a = 1;
console.log(a); // 1
複製程式碼
那麼這個過程就很好理解了。
但是如果有多個同名變數呢?
同名變數宣告
同一作用域下,對於同名變數宣告,採用的是忽略原則,後宣告的會被忽略,變數的賦值,會採取覆蓋原則。
- 同一作用域下同名變數宣告
看如下程式碼:
'use strict';
console.log(a); // undefined
var a = 1;
console.log(a); // 1
var a = 2;
console.log(a); // 2
複製程式碼
解析後的程式碼如下:
'use strict';
var a;
console.log(a); //undefined
a = 1;
console.log(a); // 1
a = 2;
console.log(a); // 2
複製程式碼
- 不同作用域下同名變數宣告
程式碼如下:
'use strict';
console.log(a); // undefined
var a = 1;
function b() {
console.log(a); // undefined
var a = 2;
console.log(a); // 2
};
b();
複製程式碼
解析後的程式碼如下(此處涉及到的執行上下文環境和作用域會另有文章詳細說明):
1. 首先進入全域性上下文環境,此時程式碼解析如下:
'use strict';
function b() {
console.log(a);
var a = 2;
console.log(a);
};
var a;
console.log(a); // undefined
a = 1;
b();
複製程式碼
2. 當執行到呼叫b函式的時候,進入b函式的上下文環境,b函式的程式碼被解析時,如下:
var a;
console.log(a); // undefined
a = 2;
console.log(a); 2
複製程式碼
在不同作用域中,就近原則,如果在當前作用域中找到,則不再向上一級作用域查詢,如果沒找到,則會找上一級作用域,一直找到全域性作用域。
所以下面只討論同一作用域下的情況。
同名函式宣告
同一作用域下,對於同名函式宣告,採用的是覆蓋原則,先宣告的會被覆蓋。
程式碼如下:
'use strict';
console.log(a); // function a() { console.log(2) }
function a() {
console.log(1);
};
function a() {
console.log(2);
};
console.log(a); // function a() { console.log(2) }
複製程式碼
解析後的程式碼如下:
'use strict';
function a() {
console.log(2);
};
console.log(a); // function a() { console.log(2) }
console.log(a); // function a() { console.log(2) }
複製程式碼
同一作用域下,同名的函式宣告和變數宣告
對於同名的函式宣告和變數宣告,採用的是忽略原則,函式宣告會提升到變數宣告之前,變數宣告會被忽略,函式宣告有效。
程式碼如下:
'use strict';
console.log(a); // function a() {}
var a;
function a() {};
複製程式碼
解析後的程式碼如下:
'use strict';
function a() {};
console.log(a); // function a() {}
複製程式碼
如果存在賦值操作,就會採取覆蓋原則。
看如下程式碼:
'use strict';
console.log(a); // function a() {}
var a = 1;
function a() {};
console.log(a); // 1
複製程式碼
解析後的程式碼如下:
'use strict';
function a() {};
console.log(a); // function a() {}
a = 1;
console.log(a); // 1
複製程式碼
總結
- 同一作用域下,對於同名變數宣告,採用的是忽略原則,後宣告的會被忽略,變數的賦值,會採取覆蓋原則。
- 同一作用域下,對於同名函式宣告,採用的是覆蓋原則,先宣告的會被覆蓋。
- 同一作用域下,對於同名的函式宣告和變數宣告,採用的是忽略原則,函式宣告會提升到變數宣告之前,變數宣告會被忽略,函式宣告有效。
如果有遺漏或者不對的地方,還請指正,先謝過~~~///(^v^)~~