0%

JavaScript中变量声明的几种方式

ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准。因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015。也就是说,ES6就是ES2015。

Babel是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码,从而在现有环境执行。大家可以选择自己习惯的工具来使用使用Babel,具体过程可直接在Babel官网查看。

ES6中出现了两种变量声明方式:let和const,加上已有的直接赋值和var声明,共有四种变量声明方式。

直接赋值

1
2
3
4
5
6
7
8
9
x =  1;
console.log(x); // logs "1"

console.log(a); // Throw a ReferenceError
console.log("still going"); // Never executes

b = 2;
delete this.b;
console.log(b); // Throw a ReferenceError

未声明的变量总是全局变量,在执行到该变量所在的语句之前,变量是不存在的。如果直接引用未声明、未赋值的变量,将抛出ReferenceError,之后的代码无法执行。未声明的变量在执行上下文中是可配置的(例如可被删除)。

var声明变量

1
2
3
4
5
6
7
8
9
var x = 1;
console.log(x); // logs "1"

var a;
console.log(a); // logs "undefine"
console.log("still goding"); // logs "still going"

var b = 2;
delete this.b; // return ralse, b still exist

与不赋值直接使用的方式相比,通过var声明的变量只在声明的上下文中生效(例如,函数内部声明的var变量在函数外部不可见)。并且,在所有代码执行之前var变量就被创建了,所以一般把变量声明在全局或函数的顶部,以便于区分哪些变量是函数内部的,哪些变量是全局的。var变量在上下文中是不可配置的,无法被删除(删除时抛出TypeError或者静默失败)。

基于以上区别,在ES5之前的代码中,无论是全局变量还是局部变量,都推荐使用var声明变量。

let

ES6中引入的let声明的变量在被声明的块(block)和子块中生效,而var声明的变量在整个作用域内生效(例如整个函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function varTest() {
var x = 1;
if(true) {
var x = 2; // same veriable!
console.log(x); // 2
}
console.log(x); // 2
}

function letTest() {
let x = 1;
if(true) {
let x = 2; // same veriable!
console.log(x); // 2
}
console.log(x); // 1
}

在程序或函数的中,let不像var一样在global对象上创建属性。

1
2
3
4
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

let不能重复声明同一个变量,并且在声明之前let变量都是undefine的。

1
2
3
4
5
6
7
8
9
if (x) {
let foo;
let foo; // SyntaxError thrown.
}

function do_something() {
console.log(foo); // ReferenceError
let foo = 2;
}

const

const可以在全局或函数内部定义一个常量,在声明const变量时需要为变量赋值,该变量的值赋值之后不能被改变。const声明只是创建了一个只读的引用,但const变量引用的值本身是可以改变的(例如引用一个对象)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// NOTE: Constants can be declared with uppercase or lowercase, but a common
// convention is to use all-uppercase letters.

// define MY_FAV as a constant and give it the value 7
const MY_FAV = 7;

// this will throw an error
MY_FAV = 20;

// will print 7
console.log('my favorite number is: ' + MY_FAV);

// trying to redeclare a constant throws an error
const MY_FAV = 20;

// the name MY_FAV is reserved for constant above, so this will also fail
var MY_FAV = 20;

// this throws an error also
let MY_FAV = 20;

// it's important to note the nature of block scoping
if (MY_FAV === 7) {
// this is fine and creates a block scoped MY_FAV variable
// (works equally well with let to declare a block scoped non const variable)
let MY_FAV = 20;

// MY_FAV is now 20
console.log('my favorite number is ' + MY_FAV);

// this gets hoisted into the global context and throws an error
var MY_FAV = 20;
}

// MY_FAV is still 7
console.log('my favorite number is ' + MY_FAV);

// throws an error, missing initializer in const declaration
const FOO;

// const also works on objects
const MY_OBJECT = {'key': 'value'};

// Attempting to overwrite the object throws an error
MY_OBJECT = {'OTHER_KEY': 'value'};

// However, object keys are not protected,
// so the following statement is executed without problem
MY_OBJECT.key = 'otherValue'; // Use Object.freeze() to make object immutable

// The same applies to arrays
const MY_ARRAY = [];
// It's possible to push items into the array
MY_ARRAY.push('A'); // ["A"]
// However, assigning a new array to the variable throws an error
MY_ARRAY = ['B']

参考文档

30分钟掌握ES6/ES2015核心内容
MDN var