按照前端技术趋势发展,一些顶级的前端框架如国内比较火的vue已经使用ES6语法,vue3还会使用TypeScript,所以技术升级势在必行,接下来的一段时间我会整理学习常用的ES6技术系列文章。为什么不说JavaScript,因为这是是Oracle公司的注册商标!要说ECMScript,ECMS是European computer manufactures association(欧洲计算机制造联合会)缩写。
ES2015(ES6)
新增加了两个重要的 JavaScript
关键字: let
和 const
。
-
let
声明的变量只在let
命令所在的代码块内有效。 -
const
声明一个只读的常量,一旦声明,常量的值就不能改变。
一、let命令
基本用法:
{
let a = 0;
a //0
}
a //报错 ReferenceError: a is not defined
相较于以前使用的var
,let
是在代码块内有效,而var
是在全局范围内都有效。
let
命令具有以下特性:
- let 命令关键词声明的变量不具备变量提升(hoisting)特性;
- 只在最靠近的一个块中(花括号内)有效;
- 不能重复声明;
- 暂时性死区;
特性示例:
{
a //报错 Cannot access 'a' before initialization
let a = 0;
let a = 1; //报错 Identifier 'a' has already been declared
}
a //报错 a is not defined
暂时性死区示例:
var tmp = 123;
if (true) {
tmp = 'abc'; //报错 Cannot access 'tmp' before initialization
let tmp;
}
只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding
)这个区域,不再受外部的影响。
上面代码中,存在全局变量tmp
,但是块级作用域内let
又声明了一个局部变量tmp
,导致后者绑定这个块级作用域,所以在let
声明变量前,对tmp
赋值会报错。
ES6 明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
总之,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
let
命令特别适合在for
循环中使用:
for (var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
})
}
// 输出十个 10
for (let j = 0; j < 10; j++) {
setTimeout(function(){
console.log(j);
})
}
// 输出 0123456789
变量i
是用var
声明的,在全局范围内有效,所以全局中只有一个变量i
,每次循环时,setTimeout
定时器里面的i
指的是全局变量i
,而循环里的十个setTimeout
是在循环结束后才执行,所以此时的i
都是10
。
变量j
是用let
声明的,当前的j
只在本轮循环中有效,每次循环的j
其实都是一个新的变量,所以setTimeout
定时器里面的j
其实是不同的变量,即最后输出 12345
。(若每次循环的变量j
都是重新声明的,如何知道前一个循环的值?这是因为 JavaScript
引擎内部会记住前一个循环的值)。
二、const命令
const
用来声明一个只读常量,声明之后不允许改变。意味着,一旦声明必须初始化,否则会报错。
基本用法:
const PI = "3.1415926";
PI // 3.1415926
const MY_AGE; //报错 Missing initializer in const declaration
const
命令具有以下特性:
- 用来声明常量,常量的值不能改变,声明时必须被赋值;
- 只在声明所在的块级作用域内有效;
- const 命令声明的常量也是不提升(hoisting);
- 当使用常量 const 声明时,请使用大写变量,如:UNAUTHORIZED
- 暂时性死区;
特性示例:
const UNAUTHORIZED = '401';
UNAUTHORIZED //401
UNAUTHORIZED = 500; //报错 Assignment to constant variable.
const SUCCESS; //报错 Missing initializer in const declaration.
{
ID_CARD //报错 Cannot access 'ID_CARD' before initialization
const ID_CARD = '110xxx123';
ID_CARD //110xxx123
}
ID_CARD //报错 ID_CARD is not defined
const
实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const
只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
{
const ARR = [1,2];
ARR.push(3);
ARR; // [1,2,3]
ARR = 10; // Assignment to constant variable.
}
上面代码中,常量ARR
存储的是一个地址,这个地址指向一个数组,数组本身是可写的,但如果将另一个数值赋值给ARR
就会报错,如果想将复杂类型数据冻结,可使用object.freeze
方法。
{
const ARR = Object.freeze([1,2]);
ARR.push(3); //报错 Cannot add property 2, object is not extensible
}
参考文章:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。