es6已经发版很久了,是时候学习一波了。
参考阮一峰大神的 ECMAScript 6 入门: http://es6.ruanyifeng.com/#docs/intro
关于ECMAScript、JavaScript、ES6语法的提案等需要了解的看大神的介绍就能了解的差不多了
浏览器与运行环境对ES6的支持
- 浏览器各种最新版本对90%的ES6的语法特性都实现了,可以在:http://kangax.github.io/compat-table/es6/ 查看各大浏览器对es6新特性的支持
- 可以查看node支持的es6特性: node –v8-options | grep harmony 输出结果会根据版本不同而不同
- 运行环境对es6的支持也是不一样的,大神写的工具 ES-Checker用来检查各种运行环境对es6的支持情况。http://ruanyf.github.io/es-checker/ 可以看到您当前浏览器对ex6的支持。 查看当前node环境对es6的支持
1
2
3
4# 安装 es-checker
npm install -g es-checker
# 命令行输入,返回当前环境对es6的支持程度
es-checker
BaBel 转码器
- 含义:浏览器和运行环境对ES6不是100%支持的,BaBel 是一个广泛使用的ES6转码器,可以将ES6代码转为ES5代码。这样就可以用ES6的语法编写程序,不用再担心现有的环境和浏览器是否支持
eg:1
2
3
4
5
6// 转码前
x => x
// 转码后
(function(x){
return x;
})()
上面的例子用了es6的箭头函数,BaBel将其转换为普通函数,就可以在不支持箭头函数的环境上执行了
- 配置文件 .babelrc 或者在package.json使用babel已有的包
BaBel 的配置文件是.babelrc,存放在项目的根目录下,使用BaBel的第一步就是配置这个文件
改文件用来设置转码规则和插件,基本格式如下:1
2
3
4{
"presets": [],
"plugins": []
}
presets 字段设定转码规则,官方提供的有规则集,可以根据需要安装1
2
3
4
5
6
7
8
9// 最新转码规则 命令行 安装preset
npm install --save-dev babel-preset-latest
// 将 preset "latest" 规则加入.babelrc 文件
{
"presets": [
"latest"
],
"plugins": []
}
- 更多的转码可以参考大神的书,也可参考:https://www.babeljs.cn/ 这里本人理解没有那么深刻
ES6新特性
一些常用的特性,比较深入的知识还没有学习研究
let 和 const
- let
1 基本用法:let 用来声明变量,类似于 var,但是使用let为代码增加了块级作用域,声明的变量只能在块级作用域内有效,一个花括号是一个块级作用域
eg:1
2
3
4
5
6{
let a = 10;
var b = 30;
}
console.log(a) //报错 ReferenceError: a is not defined
console.log(b) // 30
2 let声明的变量不存在变量提升
var 命令声明的变量存在变量提升现象,就是变量在未声明之前使用,不会报错并且会赋值为 undefined。
eg:1
2console.log(c); // undefined
var c = '测试变量声明提升';
let 命令改变了语法行为,使用let声明的变量一定要在声明之后使用,否则报错
eg:1
2console.log(d); // ReferenceError: d is not defined
let d = 'let声明变量前使用该变量';
3 let声明变量的暂时性死区
只要块级作用域内存在let命令,使用let命令声明的变量就不会受外部的影响;在该块级作用域内如果在声明变量前使用该变量就会报错,变量一定要在 let 声明后使用
eg:1
2
3
4
5
6
7
8
9
10
11
12
13
14var temp = '全局作用域';
if (1) {
temp = '全局'; // ReferenceError: temp is not defined
console.log(temp); // ReferenceError: temp is not defined
let temp;
console.log(temp); // undefined
temp = 'let块级作用域';
console.log(temp); //let块级作用域
var y = y; // undefined
let x = x; // ReferenceError: x is not defined
}
4 不允许重复声明
let 不允许在相同的块级作用域内重复声明同一个变量
eg1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24function func() {
var a = 1;
let a = 2;
}
func(); // SyntaxError: Identifier 'a' has already been declared
function func1() {
let b = 2;
let b = 20;
}
func1(); // SyntaxError: Identifier 'b' has already been declared
// 在函数内部不能重复声明参数
function func2(inx) {
let inx;
}
func2(); // SyntaxError: Identifier 'inx' has already been declared
// 使用var重复声明参数不会报错
function func3(inx) {
var inx;
console.log(inx);
}
func3(); // undefined
- const
1 const声明的是一个常量,一旦声明,常量的值就不能改变了。
eg:1
2
3const PI = 3.1415926;
console.log(PI); // 3.1415926
PI = 5; // TypeError: Assignment to constant variable.
2 const 如果只声明不赋值也会报错
eg:1
const z; // SyntaxError: Missing initializer in const declaration
3 const 的作用域和 let一样,只在声明所在的块级作用域有效1
2
3
4if (1) {
const max = 5;
}
console.log(max); // ReferenceError: max is not defined
4 const 命令声明的变量也是不能提升的,同样存在暂时性死区,只能在声明的位置后面使用1
2console.log(min); // ReferenceError: min is not defined
const min = 1;
5 const 声明的常量,和let一样不能重复声明1
2
3
4
5var message = 'cj';
let age = 22;
const message = 'xjj'; // SyntaxError: Identifier 'message' has already been declared
const age = 21; // SyntaxError: Identifier 'age' has already been declared
变量的解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,属于“模式匹配”
- 数组的解构赋值
等号左边和右边都需是数组1
2
3
4
5
6
7
8// 之前的写法
let a = 1;
let b = 2;
let c = 3;
// es6的写法
let [a, b, c] = [1, 2, 3];
// 只要等号两边的模式一致,等号左边的变量就会被赋值右边对应的值
// 即:a=1, b=2, c=3
1.嵌套数组的解构
eg.1
2
3
4
5
6
7let [a, [[b], c]] = [1, [[2], 3]];
// a=1, b=2, c=3
let [, , d] = ['1', '2', '3'];
// d=3
let [x, y, ...z] = ['a'];
// x=a, y=undefined, z=[]
// 解构不成功,找不到匹配的模式,变量的值为undefined,就相当于定义变量未赋值
2.不完全解构,即左边的变量都能匹配到右边的一部分数组
eg.1
2
3
4let [m, n] = [1, 2, 3];
// m=2. n=3
let [a, [b], d] = [1, [2, 3], 4];
// a=1, b=2, d=4
3.允许指定默认值
当数组设默认值了,等号右边的值为undefined时,等号左边的变量会取默认值
eg.1
2let [x=1] = [undefined];
// x=1
- 对象的解构赋值
对象的解构赋值与数组有一个重要的不同,数组的元素是按照次序排列的,变量的取值根据元素的位置决定的;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
1.这种是属性名跟变量名相同, bar:bar, 可以简写为bar1
2
3
4let {bar, foo} = {foo: 'aaa', bar: 'bbb'};
// bar='bbb', foo='aaa'
let {baz} = {foor: 'aaa', bar: 'bbb'};
// baz='undefined'
如果等号左边的属性名跟右边的有对应,则赋值成功,跟次序无关,如果没有找到对应的,该变量就是undefined
2.属性名跟变量名不一致1
2
3
4
5
6
7// foo是匹配的模式,baz是变量,根据foo匹配到等号右侧的值,真正赋值的是baz
let {foo:baz} = {foo: 'aaa', bar:'bbb'};
// baz: 'aaa'
let obj = {first: 'hello', last: 'world'};
let {first:f, last: l} = obj;
// f:'hello', l:'world'
3.对象的变量解构也可以用于嵌套的对象
eg.1
2
3
4
5
6
7
8let obj = {
p: [
'hello',
{y: 'world'}
]
};
let {p:[x, {y}]} = obj;
// x:'hello', y:'world'
3.对象的变量赋值同样可以设置默认值
eg. 默认值生效的条件是,对象的属性值严格等于 undefined1
2let {x=1} = {};
// x:1
- 函数参数的解构赋值
1.函数的参数也可以使用解构赋值,规则按照数组或者对象的结构赋值来
eg.1
2
3
4function add([x,y]) {
return x + y
}
add([2,3]);
字符串的扩展
最常用的是模板字符串,如果有变量的话,传统的是要用jq拼字符串,很繁琐,现在es6中可以使用``反引号来写,变量用${变量}
eg.1
`heloo, anyone, i am ${name}`
${大括号里可以写js表达式}
数组的扩展
扩展运算符(…)三个点,将一个数组转为用逗号分隔的参数序列
[1, …arr],是常用的组合,合并数组
函数的扩展
参数可以使用默认值, 当参数值为undefined时,采用默认值1
2
3
4
5function log(x, y='world') {
console.log(x, y);
}
log('hello'); // hello, world
log('hello', 'es6'); // hello, es6