一、變量聲明
JavaScript有三種聲明:
- var 聲明一個變量
- let 聲明一個塊作用域的局部變量(block scope local variable)
- const 聲明一個只讀的常量。
1. 變量求值
- 用
var
或let
聲明的且未賦初值的變量,值會被設定為undefined
。 - 試圖訪問一個未聲明的變量或者訪問一個使用
let
聲明的但未初始化的變量會導致一個ReferenceError
異常被拋出。
var a;
console.log('The value of a is ' + a); // The value of a is undefined
console.log('The value of b is ' + b); // The value of b is undefined
var b;
console.log('The value of c is ' + c); // Uncaught ReferenceError: c is not defined
let x;
console.log('The value of x is ' + x); // The value of x is undefined
console.log('The value of y is ' + y); // Uncaught ReferenceError: y is not defined
let y;
- 數值類型環境中 undefined 值會被轉換為 NaN。
var a;
a + 2; // Evaluates to NaN
- 當你對一個
null
變量求值時,空值null
在數值類型環境中會被當作0
來對待
var n = null;
console.log(n * 32); // Will log 0 to the console
2. 變量的作用域
- 在所有函數之外聲明的變量,叫做全局變量,因為它可被當前文檔中的任何其他代碼所訪問。
- 在函數內部聲明的變量,叫做局部變量,因為它只能在該函數內部訪問。
- 語句塊作用域
ECMAScript 6 之前的JavaScript沒有 語句塊作用域;相反,語句塊中聲明的變量將成為語句塊所在代碼段的局部變量。例如,如下的代碼將在控制臺輸出 5,因為 x 的作用域是聲明了 x 的那個函數(或全局范圍),而不是 if 語句塊。
if (true) {
var x = 5;
}
console.log(x); // x is 5
如果使用 ECMAScript 6 中的 let 聲明,上述行為將發生變化。
if (true) {
let y = 5;
}
console.log(y); // ReferenceError: y is not defined
3. 變量聲明提升
變量聲明提升(variable hoisting),JavaScript 變量的另一特別之處是,你可以引用稍后聲明的變量而不會引發異常,然而提升后的變量將返回 undefined 值。
1).
console.log(x === undefined); // true
var x = 3;
等價于
var x;
console.log(x === undefined); // true
x = 3;
2).
// will return a value of undefined
var myvar = 'my value';
(function() {
console.log(myvar); // undefined
var myvar = 'local value';
})();
等價于
// will return a value of undefined
var myvar = 'my value';
(function() {
var myvar;
console.log(myvar); // undefined
myvar = 'local value';
})();
- 在 ECMAScript 2015 中,
let
(const
)將不會提升變量到代碼塊的頂部。因此,在變量聲明之前引用這個變量,將拋出錯誤ReferenceError
。
console.log(x); // ReferenceError
let x = 3;
二、函數提升
對于函數,只有函數聲明會被提升到頂部,而不包括函數表達式(表達式定義的函數,稱為匿名函數,匿名函數沒有函數提升)。
- 函數聲明
foo(); // "bar"
function foo() {
console.log('bar');
}
- 函數表達式
baz(); // TypeError: baz is not a function
var baz = function() {
console.log('bar2');
};
【注】:此時的 baz
相當于一個聲明的變量,類型為 undefined
。由于 baz
只是相當于一個變量,因此瀏覽器認為 baz()
不是一個函數。