Var
变量
ECMAScript 的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。每个变量仅仅是一个用于保存值的占位符而已。定义变量时要使用var
操作符(注意var
是一个关键字),后跟变量名;
1 | var message; // undefined |
未经过初始化的变量,会保存一个特殊的——值 undefined
,表示未经初始化
可以在修改变量值的同时修改值的类型
1 | var message = 'hi'; |
用var
声明的一个变量将成为定义该变量的作用域中的局部变量,如果在函数内部中使用var
声明一个变量,这个变量在函数退出后就会被销毁,例如:
1 | function test () { |
这里,变量message是在函数中使用var
定义的。当函数被调用时,就会创建变量并为其赋值。而在此之后,这个变量又会立即被销毁,因此就会导致错误。
如果在函数内部省略var
操作符,会创建一个全局变量:
请看下面例子:
1 | function test() { |
这里,省略了var
操作符,因而message变成了全局变量,只要调用过一次test()
函数,这个变量就有了定义,也就可以在函数外部的任何地方被访问到。
不推荐在局部作用域中定义全局变量,难以维护,如果有意地忽略了var
操作符,会由于相应的变量不会马上就有定义而导致不必要的混乱。给未经声明的变量赋值在严格模式下会导致跑出ReferenceError
错误
可以使用一条语句定义多个变量(初始化或不初始化均可)用逗号分隔开即可:
例子如下:
1 | var message = 'hi', |
在严格模式(‘use strict’)下,不能定义名为eval
或arguments
的变量名,否则会报语法错误。
例子如下:
1 | // Strict Mode 开启严格模式 ; |
因为在JavaScript中eval
和arguments
都是字面量
Let
命令
基本用法
ES6中新增了let
命令,用于声明变量。用法类似与var
,但是所声明的变量只在let
命令所在的代码块内有效
如下例子:
1 | { |
上面的代码在代码块中分别用let
和var
声明了两个变量。然后在代码块之外调用这两个变量,结果let
声明的变量报错,var
声明的变量返回了正确的值。表明,let
声明的变量只在其所在的代码块有效。
for
循环的计数器,很适合使用let
命令
1 | for (let i = 0; i < arr.lenght; i++) {} |
以上代码中的计数器i,只在for
循环体内有效,所以console.log(i)
会报ReferenceError
错误
改成下面的代码,如果使用var
来声明,最后的结果将输出什么?
1 | for (var i = 0; i < 10; i++) {}; |
1 | var a = []; |
上面的代码中,变量i是var
声明的,在全局范围内都有效。所以每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i值。
如果使用let
,声明的变量仅在块级作用域内有效,最后将输出6
1 | var a = []; |
上面的代码中,变量i是let
声明的,当前的i只在本轮循环有效。所以每一次循环的i其实都是一个新的变量,于是最后输出的是6。
不存在变量提升
let
不像var
会
暂时性死区(TDZ / Temporal Dead Zone)
什么是暂时性死区?
- TDZ 并不是某个地方, 或是内存中的某个区域,而是变量被声明和被初始化之间的这段时间。
1 | console.log(aVar); // undefined |
1 | var x = 1; |