新的声明方式
声明方式
var 声明语句声明一个变量,并可选地将其初始化为一个值。
语法:
| 1 | var varname1 = [= value1][, varname2][= value2]...[, varnameN][=valueN]; | 
varname
变量名。变量名可以定义为任何合法标识符。
valueN
变量的初始化值。默认值是 undefined。
描述:
变量声明,无论发生在何处,都在执行任何代码之前进行处理。
用var声明的变量的作用域是它当前的执行上下文。
重新声明一个 JavaScript 变量,它将不会丢失其值。
将赋值给未声明变量的值在执行赋值时将其隐式地创建为全局变量(它将成为全局对象的属性)。
声明和未声明变量之间的差异是:
- 声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的。 - 1 
 2
 3
 4
 5
 6
 7
 8
 9- function x(){ 
 y = 1; // 在严格模式(strict mode)下会抛出 ReferenceError 异常
 var z = 2;
 }
 x();
 console.log(y); // 打印 “1”
 console.log(z); // 抛出 ReferenceError: z 未在 x 外部声明
- 声明变量在任何代码执行前创建,而非声明变量只有在执行赋值操作的时候才会被创建。 - 1 
 2
 3
 4- console.log(y); 
 y = 1;
 console.log(y);
 // 打印 Error: y is not defined- 1 
 2
 3- console.log(y); // undefined 变量的初始化值。默认值是 undefined。 
 var y = 1;
 console.log(y); // 1
- 声明变量是它所在上下文环境的不可配置属性,非声明变量是可配置的(如非声明变量可以被删除)。 - 1 
 2
 3
 4
 5
 6
 7
 8- var a = 1; 
 b = 2;
 delete this.a; // 在严格模式(strict mode)下抛出TypeError,其他情况下执行失败并无任何提示。
 delete this.b;
 console.log(a, b); // 抛出ReferenceError。
 // 'b'属性已经被删除。- 由于这三个差异,未能声明变量将很可能导致意想不到的结果。因此,建议始终声明变量,无论它们是在函数还是全局作用域内。 而且,在 ECMAScript 5 严格模式下,分配给未声明的变量会引发错误。 
变量提升
由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。
| 1 | bla = 2; | 
因此,建议始终在作用域顶部声明变量(全局代码的顶部和函数代码的顶部),这可以清楚知道哪些变量是函数作用域(本地),哪些变量在作用域链上解决。
重要的是,提升将影响变量声明,而不会影响其值的初始化。当到达赋值语句时,该值将确实被分配:
| 1 | function do_something() { | 
声明并初始化两个变量:
| 1 | var a = 0, b = 0; | 
给两个变量赋值成字符串值:
| 1 | var a = "A"; | 
多个变量的初始化
| 1 | var x = 0; | 
隐式全局变量和外部函数作用域
| 1 | var x = 0; // x是全局变量,并且赋值为0。 | 
let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。
语法:
| 1 | let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]]; | 
var1, var2, …, varN
变量名。必须是合法的标识符。
value1, value2, …, valueN
变量的初始值。可以是任意合法的表达式。
描述:
let 允许你声明一个作用域被限制在块级中的变量、语句或者表达式。与 var 关键字不同的是,var 声明的变量只能是全局或者整个函数块的。 var 和 let 的不同之处在于后者是在编译时才初始化。
就像const 一样,let不会在全局声明时(在最顶部的范围)创建window 对象的属性。
作用域规则
let声明的变量只在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。
| 1 | function varTest() { | 
在函数或代码顶部,let 不会在全局对象里新建一个属性。var声明会给全局对象新增属性。
| 1 | var x = 'global'; | 
模仿私有成员
在处理构造函数的时候,可以通过 let 声明而不是闭包来创建一个或多个私有成员。
| 1 | var Thing; | 
可以使用var创建和闭包具有相同隐私模式的局部变量,但是它们需要函数作用域(通常是模块模式中的IIFE),而不仅仅是上面示例中的块作用域。
重复声明
在同一个函数或块作用域中重复声明同一个变量会引起SyntaxError。
| 1 | if (x) { | 
然而,需要特别指出的是,一个嵌套在 case 子句中的块会创建一个新的块作用域的词法环境,就不会产生上诉重复声明的错误。
| 1 | let x = 1; | 
暂存死区
与通过 var 声明的有初始化值 undefined 的变量不同,通过 let 声明的变量直到它们的定义被执行时才初始化。在变量初始化前访问该变量会导致 ReferenceError。该变量处在一个自块顶部到初始化处理的“暂存死区”中。
| 1 | function do_something() { | 
暂存死区与 typeof
与通过var声明的变量, 有初始化值 undefined和只是未声明的变量不同的是,如果使用typeof检测在暂存死区中的变量, 会抛出ReferenceError异常:
| 1 | // prints out 'undefined' | 
const
常量是块级作用域,很像使用 let 语句定义的变量。常量的值不能通过重新赋值来改变,并且不能重新声明。
语法:
const name1 = value1 [, name2 = value2 [, … [, nameN = valueN]]];
nameN
常量名称,可以是任意合法的标识符。
valueN
常量值,可以是任意合法的表达式。
描述:
此声明创建一个常量,其作用域可以是全局或本地声明的块。 与var变量不同,全局常量不会变为窗口对象的属性。需要一个常数的初始化器;也就是说,您必须在声明的同一语句中指定它的值(这是有道理的,因为以后不能更改)。
const 声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容(例如,其参数)。
一个常量不能和它所在作用域内的其他变量或函数拥有相同的名称。
示例
| 1 | // 注意: 常量在声明的时候可以使用大小写,但通常情况下全部用大写字母。 | 
总结归纳
使用var声明建议
建议始终在全部代码的顶部和函数代码的顶部声明变量.
使用var需要注意:
声明提前/变量提升。(变量声明在任意代码执行之前处理)
未声明的变量是全局变量,未声明的变量赋值才会被创建。
全局声明时,创建 window 对象的属性
| 1 | var a; | 
使用let需要注意:
同一个函数或块作用域不能重复声明。
暂存死区(通过 let 声明的变量直到它们的定义被执行时才初始化)。
不会创建window 对象的属性
| 1 | console.log(typeof undeclaredVariable); // undefined | 
使用const建议:
建议变量名全部用大写字母。例如MY_FAV
使用const需要注意:
同一个函数或块作用域不能重复声明。
不能重新赋值。
声明同时指定值,值只读引用,值是对象时可改变。
以上是我对下列视频及文章的归纳和总结。
ES6 免费视频教程
参考资料:
MDN var
MDN let
MDN var
ECMAScript 6 入门-let和const 命令
ES6的开发环境搭建
相关代码仓库:
ES6
install_url to use ShareThis. Please set it in _config.yml.