JS-声明
var
声明一个变量,可同时将其初始化为一个值。
变量声明,无论发生在何处,都在执行任何代码之前进行处理。用 var 声明的变量的作用域是它当前的执行上下文,它可以是嵌套的函数,也可以是声明在任何函数外的变量。如果你重新声明一个 JavaScript 变量,它将不会丢失其值。
> 简而言之, var
声明的变量只能是全局或者整个函数块的。
将赋值给未声明变量的值在执行赋值时将其隐式地创建为全局变量(它将成为全局对象的属性)。声明和未声明变量之间的差异是:
1. 声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的。
1 | function x() { |
2. 声明变量在任何代码执行前创建,而非声明变量只有在执行赋值操作的时候才会被创建。
1 | console.log(a); // 抛出ReferenceError。 |
3. 声明变量是它所在上下文环境的不可配置属性,非声明变量是可配置的(如非声明变量可以被删除)。
1 | var a = 1; |
由于这三个差异,未能声明变量将很可能导致意想不到的结果。因此,建议始终声明变量,无论它们是在函数还是全局作用域内。 而且,在 ECMAScript 5 严格模式下,分配给未声明的变量会引发错误。
变量提升
由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。
1 | bla = 2 |
因此,建议始终在作用域顶部声明变量(全局代码的顶部和函数代码的顶部),这可以清楚知道哪些变量是函数作用域(本地),哪些变量在作用域链上解决。
重要的是,提升将影响变量声明,而不会影响其值的初始化。当到达赋值语句时,该值将确实被分配:
1 | function do_something() { |
隐式全局变量和外部函数作用域
看起来像是隐式全局作用域的变量也有可能是其外部函数变量的引用。
x 是全局变量,并且赋值为0。
y 被声明成函数 a 作用域的变量,然后赋值成 2。
创建新的全局变量 z,并且给 z 赋值为 5。
1 | var x = 0; // x是全局变量,并且赋值为0。 |
let
let
不会在全局声明时(在最顶部的范围)创建window
对象的属性。
**let
**允许你声明一个作用域被限制在 块
级中的变量、语句或者表达式。
作用域规则
let声明的变量只在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。
1 | function varTest() { |
在程序和方法的最顶端,let不像 var 一样,let不会在全局对象里新建一个属性。比如:
位于函数或代码顶部的var声明会给全局对象新增属性, 而let不会。例如:
1 | var x = 'global'; |
重复声明
在同一个函数或块作用域中重复声明同一个变量会引起SyntaxError
。
1 | if (x) { |
暂存死区
与通过 var 声明的有初始化值 undefined
的变量不同,通过 let
声明的变量直到它们的定义被执行时才初始化。在变量初始化前访问该变量会导致 ReferenceError。该变量处在一个自块顶部到初始化处理的“暂存死区”中。
所以说变量一定要先声明, 后使用.
其他情况
用在块级作用域中时, let将变量的作用域限制在块内, 而var声明的变量的作用域是在函数内。
1 | var a = 1; |
而这种var 与 **let
**合并的声明方式会报SyntaxError错误, 因为**var**
会将变量提升至块的顶部, 这会导致隐式地重复声明变量。
1 | let x = 1; |
const
声明一个只读的命名常量。
常量是块级作用域,很像使用 let 语句定义的变量。常量的值不能通过重新赋值来改变,并且不能重新声明。
const
****声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容(例如,其参数)。
一个常量不能和它所在作用域内的其他变量或函数拥有相同的名称。
常量示例
下面的例子演示了常量的特性。在浏览器的控制台试一下这个例子。
1 | // 注意: 常量在声明的时候可以使用大小写,但通常情况下全部用大写字母。 |
参考
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/var
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/const