'js變量的作用域、變量的提升、函數的提升'

JavaScript ECMAScript 前端王小明 2019-08-08
"

變量的作用域

在函數之外聲明的變量,叫做全局變量,因為它可被當前文檔中的任何其他代碼所訪問。在函數內部聲明的變量,叫做局部變量,因為它只能在當前函數的內部訪問。

ECMAScript 6 之前的 JavaScript 沒有 語句塊作用域;相反,語句塊中聲明的變量將成為語句塊所在函數(或全局作用域)的局部變量。例如,如下的代碼將在控制檯輸出 5,因為 x 的作用域是聲明瞭 x 的那個函數(或全局範圍),而不是 if 語句塊。

if (true) {
var x = 5;
}
console.log(x); // 5
如果使用 ECMAScript 6 中的 let 聲明,上述行為將發生變化。
if (true) {
let y = 5;
}
console.log(y); // ReferenceError: y 沒有被聲明

變量提升

JavaScript 變量的另一個不同尋常的地方是,你可以先使用變量稍後再聲明變量而不會引發異常。這一概念稱為變量提升;JavaScript 變量感覺上是被“提升”或移到了函數或語句的最前面。但是,提升後的變量將返回 undefined 值。因此在使用或引用某個變量之後進行聲明和初始化操作,這個被提升的變量仍將返回 undefined 值。

/**
* 例子1
*/
console.log(x === undefined); // true
var x = 3;
/**
* 例子2
*/
// will return a value of undefined
var myvar = "my value";
(function() {
console.log(myvar); // undefined
var myvar = "local value";
})();

上面的例子,也可寫作:

/**
* 例子1
*/
var x;
console.log(x === undefined); // true
x = 3;
/**

* 例子2

*/
var myvar = "my value";
(function() {
var myvar;
console.log(myvar); // undefined
myvar = "local value";
})();

由於存在變量提升,一個函數中所有的var語句應儘可能地放在接近函數頂部的地方。這個習慣將大大提升代碼的清晰度。

在 ECMAScript 6 中,let(const)將不會提升變量到代碼塊的頂部。因此,在變量聲明之前引用這個變量,將拋出引用錯誤(ReferenceError)。這個變量將從代碼塊一開始的時候就處在一個“暫時性死區”,直到這個變量被聲明為止。

console.log(x); // ReferenceError
let x = 3;

函數提升

對於函數來說,只有函數聲明會被提升到頂部,而函數表達式不會被提升。

/* 函數聲明 */
foo(); // "bar"
function foo() {
console.log("bar");
}
/* 函數表達式 */
baz(); // 類型錯誤:baz 不是一個函數
var baz = function() {
console.log("bar2");
};

"

變量的作用域

在函數之外聲明的變量,叫做全局變量,因為它可被當前文檔中的任何其他代碼所訪問。在函數內部聲明的變量,叫做局部變量,因為它只能在當前函數的內部訪問。

ECMAScript 6 之前的 JavaScript 沒有 語句塊作用域;相反,語句塊中聲明的變量將成為語句塊所在函數(或全局作用域)的局部變量。例如,如下的代碼將在控制檯輸出 5,因為 x 的作用域是聲明瞭 x 的那個函數(或全局範圍),而不是 if 語句塊。

if (true) {
var x = 5;
}
console.log(x); // 5
如果使用 ECMAScript 6 中的 let 聲明,上述行為將發生變化。
if (true) {
let y = 5;
}
console.log(y); // ReferenceError: y 沒有被聲明

變量提升

JavaScript 變量的另一個不同尋常的地方是,你可以先使用變量稍後再聲明變量而不會引發異常。這一概念稱為變量提升;JavaScript 變量感覺上是被“提升”或移到了函數或語句的最前面。但是,提升後的變量將返回 undefined 值。因此在使用或引用某個變量之後進行聲明和初始化操作,這個被提升的變量仍將返回 undefined 值。

/**
* 例子1
*/
console.log(x === undefined); // true
var x = 3;
/**
* 例子2
*/
// will return a value of undefined
var myvar = "my value";
(function() {
console.log(myvar); // undefined
var myvar = "local value";
})();

上面的例子,也可寫作:

/**
* 例子1
*/
var x;
console.log(x === undefined); // true
x = 3;
/**

* 例子2

*/
var myvar = "my value";
(function() {
var myvar;
console.log(myvar); // undefined
myvar = "local value";
})();

由於存在變量提升,一個函數中所有的var語句應儘可能地放在接近函數頂部的地方。這個習慣將大大提升代碼的清晰度。

在 ECMAScript 6 中,let(const)將不會提升變量到代碼塊的頂部。因此,在變量聲明之前引用這個變量,將拋出引用錯誤(ReferenceError)。這個變量將從代碼塊一開始的時候就處在一個“暫時性死區”,直到這個變量被聲明為止。

console.log(x); // ReferenceError
let x = 3;

函數提升

對於函數來說,只有函數聲明會被提升到頂部,而函數表達式不會被提升。

/* 函數聲明 */
foo(); // "bar"
function foo() {
console.log("bar");
}
/* 函數表達式 */
baz(); // 類型錯誤:baz 不是一個函數
var baz = function() {
console.log("bar2");
};

js變量的作用域、變量的提升、函數的提升

"

相關推薦

推薦中...