按照惯例,ECMAScript 标识符使用驼峰大小写形式。
ES5 增加了严格模式的概念,严格模式是一种不同的 JavaScript 解析和执行模型,所有现代浏览器都支持严格模式。
ES 变量是松散类型的,这意味着变量可以用于保存任何类型的数据,每个变量只不过是一个用于保存任意值的命名占位符;var 在 ES 的所有版本中都能使用,而 const 和 let 只能在 ES6 及以后的版本中使用。
var 关键字
- var 可以定义任何类型的值,当其指定的变量未初始化时,变量值为 undefined;
- 使用 var 在函数内部定义变量,其作用域为函数内部;若在函数内部省略 var 操作符,变量将成为全局变量(不推荐,在严格模式下给未声明的变量赋值,将会抛出 ReferenceError)。
- 使用 var 声明变量时,变量声明会自动提升到函数作用域的顶部,即可以先使用,再声明;
- 可以使用 var 反复多次声明同一个变量。
let 关键字
- let 声明的范围是块作用域,而不是函数作用域;
- let 不允许同一个块作用域中出现冗余声明;
- 不允许 let 和 var 在同一作用域中多次声明同一个变量,因为这两个子声明的不是不同类型的变量,他们只是指出变量在相关作用域中如何存在,冗余声明会出现 SyntaxError:
var name; let name //SyntaxError
- let 声明的变量不会在作用域中被提升,即必须先声明再使用——在 let 声明之前的执行瞬间被称为“暂时性死区”;
- let 在全局作用域下声明的变量不会成为 window 对象的属性,var 声明的变量会:
var name = 'xiaoming'; console.log(window.name); //'xiaoming' let age = 10; console.log(window.age); //undefined
- 不可能检查前面是否使用过 let 声明过同名变量。使用 var 声明的时候,JavaScript 引擎会自动将多余的声明在作用域顶部合并为一个声明;但是 let 的作用域是块,所以不可能检查前面是否使用 let 声明过同名变量,所以也就不可能在没有声明的情况下声明它(if 和 try-catch 均不可以)。有如下例子:
if (typeof name === 'undefined') { let name; //如果 name 没被声明过,便声明它 //但此时的 name 被限制在 if 的作用域内部 } name = 'xiaoming'; //此处相当于一个全局赋值
- 使用 var 定义 for 循环中的迭代变量会渗透到循环体的外部,但使用 let 定义的迭代变量被限制在 for 循环的循环块内部;
- 使用 let 定义的迭代变量,JavaScript 会为每个迭代循环声明一个新的迭代变量,每个循环引用不同的迭代变量实例,而使用 var 定义时,只会保存时循环结束时的变量值:
for (var i = 0; i < 5; ++i) { setTimeout(() => console.log(i), 0) } //输出 5 5 5 5 5 for (let i = 0; i < 5; ++i) { setTimeout(() => console.log(i), 0) } //输出 0 1 2 3 4
const 关键字
- 声明变量时必须同时初始化变量,并且变量值不可修改;
- 作用域为块;
- const 声明的限制仅限于它指向的变量的引用,若 const 变量引用的是一个对象,则可以改变对象内部的属性;
- const 不能用于声明迭代变量(迭代变量会自增)。
限制自己只使用 let 和 const 有助于提升代码质量,因为变量有了明确的作用域、声明位置以及不变的值。