-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
在 ES6 之前通常定义变量的通过 var
关键字. 如下:
var a = 1;
var fn = function(){}
function test (){
console.log(a); // undefined
var a = 2;
}
在 ES6 之中引入 let
和 const
, 为什么需要引入这两个关键字. 先来回顾下 var
相关的内容:
- 全局声明的变量会添加
window
上
"use strict"
var a = 1;
console.log(window.a); //=> 1
var RegExp = "Hello";
console.log(RegExp); //=> "Hello"
console.log(window.RegExp); //=> "Hello"
带来的问题就是, 容易覆盖 window 上内置对象.
- 允许重复声明(同一个作用域中)
"use strict"
var a = 1;
var a = 2;
console.log(a); //=> 2
- 变量提升(Hosting)
console.log(a); //=> undefined
var a = 1;
function test() {
console.log(a); //=> undefined
var a = 2;
console.log(a); //=> 2
}
- 不存在块级作用域
{
var a = 1;
}
console.log(a); //=> a
for (var i =0; i < 5; i++){
setTimeout(function(){
console.log(i);
})
}
// => 5 5 5 5 5
了解 var
基本概念后, 再来了解下 let
相关的.
- 全局声明的变量不会添加
window
上
let a = 1;
console.log(a); //=> 1
console.log(window.a); //=> undefined
let RegExp = "Hello";
console.log(RegExp); //=> "Hello"
console.log(window.RegExp); //=> ƒ RegExp() { [native code] }
只会形成遮蔽, 并不会覆盖其内置对象.
- 不允许重复声明(同一个作用域中)
let a = 1;
let a = 1;
//=> Uncaught SyntaxError: Identifier 'a' has already been declared
这样避免被覆盖的问题, 减少程序产生莫名其妙的问题.
- 不存在变量提升
console.log(a); //=> Uncaught ReferenceError: a is not defined
let a = 1;
- 暂时性死区(temporal dead zone)
function test() {
console.log(a); //=> Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 2;
console.log(a); //=> 2
}
test();
TDZ
并不是ECMA的标准, 只是为了方便描述let
和const
不提升效果. JavaScript 引擎在扫码代码时, 发现变量是通过 var 声明的则提升变量到作用域顶部, 如果是通过let
orconst
则会把变量放入到 TDZ 中, 当在声明之前访问则会报错.
- 存在块级作用域
{
let a = 1;
}
console.log(a); //=> Uncaught ReferenceError: a is not defined
for (let i =0; i < 5; i++){
setTimeout(function(){
console.log(i);
})
}
// => 0 1 2 3 4
从let
中可以看到相比 var
带来的不同, 使代码变得更加健壮, 减少莫名其妙的问题.
了解完 var
、let
之后, 再来了解下 const
.
其实 let
与 const
几乎差不多, 区别.
- 不允许重复赋值(声明的时必须赋值)
const a = 1;
a = 1; //=> Uncaught SyntaxError: Identifier 'a' has already been declared
for
循环
for (const i =0; i < 5; i++){
setTimeout(function(){
console.log(i);
})
}
//=> Uncaught TypeError: Assignment to constant variable.
在 for in
或 for of
中与 let
一致.
对比
描述 | var | let |
---|---|---|
Hosting | ✅ | ❌ |
Block Scoped | ❌ | ✅ |
re-declared | ✅ | ❌ |
Brower Support | 所有浏览器 | 现代浏览器 |
Compatibility | 支持所有浏览器及JS运行时环境 | 需要借助类似 babel 转换成老版本, 从而才能支持所有浏览器 |
最佳实践
默认使用const
, 只在确定需要修改变量值时使用 let
, 这样可以在某种程度上实现代码的不可变, 从而防止某些错误的产生.
总结
let
和const
为 JavaScript 引入块级作用域的概念let
和const
的特性大大提升产生错误的几率- 不会添加到 window 上
- 不允许重复声明
- 块级作用域
- TDZ
- 不允许重复赋值(const)
Metadata
Metadata
Assignees
Labels
No labels