String
新特性的方法 基本不支持IE浏览器
String.fromCodePoint(6特性)
String.prototype.codePointAt(6特性)
for...of
for(let a of b){console.log(a)} // 合for循环不同在,它支持遍历大于0xffff的字符
includes()、endsWith()、startWith()
repeat()
padStart() 、padEnd()
模板字符串
let str = 'console.log(hello' + `${name})`;
let func = new Function('name', str);
func('xiong');
标签模板
alert`1234`
// 等价于
alert(1234)
String.raw
let a = 10;
String.raw`\`hello${a}\``
// return \`hello10\`
通常用来转换模板字符串为不同字符串。
Reg
支持修改正则修饰符
new RegExp(/test/gi, 'i')
增加u(unicode)修饰符
增加y(粘连)修饰符
具名组匹配和后行断言(提按)
Function
函数参数默认值
function({x = 0 ,y = 0 } = {})
rest参数
function(...values){
console.log(values.length) //
}
箭头函数
Symbol(类似String的新原始数据类型)
Promise
- then 和 catch方法都会返回一个新的Promise对象同时状态为resolved
- resolved状态的的所有promise对象,都会执行then回调函数
- promise对象内的错误不会影响到promise对象外部代码,
因此使用setTimeout方式可将错误抛出到全局中(因为setTimout执行时,promise已经完成所以是全局执行)
Promise.resolve()
Promise.reject()
done() 确保捕捉未捕获错误 并全局抛出
两个可用的附加方法:
// done 方法实现逻辑
Promise.prototype.done = function(handleResolve, handleReject){
this
.then(handleResolve, handleReject)
.catch(function(reson){
setTimout(function(){
throw new Error(reson)
})
})
}
// finally 接受一个普通的回调函数作为参数,该函数不管怎样都必须执行
Promise.prototype.finally = function (callback) {
let P = this.constructor;
return this.then(
value => P.resolve(callback()).then(() => value),
reason => P.resolve(callback()).then(() => { throw reason })
);
};
Iterator 遍历器
ES6中新增用于统一遍历不同数据类型的一种机制。
同时也新增了新的遍历命令for...of,前者主要供后者使用。
具备Iterator接口的数据结构(实例)可通过Symbol.iterator属性获取到遍历器,
[1,3][Symbol.iterator]
// ƒ values() { [native code] }
也能被for...of遍历。
1.原生具备 Iterator 接口的数据结构如下:
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments 对象
- NodeList 对象
上面集中数据结构可直接通过for...of命令遍历数据:
for(let i of [1,2]){
console.log(i) // 1, 2
}
2.原生不具备Iterator迭代器的数据结构,如对象,通过自定义实现
本质上,遍历器是一种线性处理,对于任何非线性的数据结构,部署遍历器接口,
就等于部署一种线性转换。不过,严格地说,对象部署遍历器接口并不是很必要,
因为这时对象实际上被当作 Map 结构使用,ES5 没有 Map 结构,
而 ES6 原生提供了。
3.对于类似数组的对象(存在数值键名和length属性)
部署 Iterator 接口,有一个简便方法,就是Symbol.iterator方法直接引用数组的 Iterator 接口。
let iterable = {
0: 'a',
1: 'b',
2: 'c',
length: 3,
[Symbol.iterator]: Array.prototype[Symbol.iterator]
};
for (let item of iterable) {
console.log(item); // 'a', 'b', 'c'
}
注:普通对象部署遍历对象,无效。
有了遍历器接口,数据结构就可以用for...of循环遍历(详见下文),也可以使用while循环遍历。
Generator
基本使用
返回一个迭代器。
- 定义
function* test(){
yield 1;
yield 2;
return 3;
}
- 使用
for(let i of test()){
console.log(i) // 1,2,3
}
- yield* 表达式
在一个 Generator 函数里面执行另一个 Generator 函数,遍历时则返回对应的另一个迭代器;
function* inner() {
yield 'hello!';
}
function* outer1() {
yield 'open';
yield inner();
yield 'close';
}
var gen = outer1()
gen.next().value // "open"
gen.next().value // 返回一个遍历器对象
gen.next().value // "close"
function* outer2() {
yield 'open'
yield* inner()
yield 'close'
}
var gen = outer2()
gen.next().value // "open"
gen.next().value // "hello!"
gen.next().value // "close"
作为对象的属性
let obj = {
* test(){
yield 1;
}
};
Generator 与 async
Generator 异步
- co模块(用于执行Generator函数的执行器)
通过Generator函数与co模块结合使用可实现异步代码的同步使用
- Generator与async
Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。
- 一个await语句后面Promise变为reject,则整个async函数就会中断。
通过try...catch可以避免这种情况:
async function f() {
try {
await Promise.reject('出错了');
} catch(e) {
}
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
另一种方法则通过添加catch处理报错:
async function f() {
await Promise.reject('出错了')
.catch(e => console.log(e));
return await Promise.resolve('hello world');
}
f()
.then(v => console.log(v))
// 出错了
// hello world
- 多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
// unrecomended 不存在继发关系
let foo = await getFoo();
let bar = await getBar();
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
两种写法,getFoo和getBar都是同时触发,这样就会缩短程序的执行时间。
async实现原理
async就是讲Generator和自动执行器包装在一个函数里而实现的。
- spawn
下面给出spawn函数的实现,基本就是前文自动执行器的翻版。
async function fn(args) {
// ...
}
// 等同于
function fn(args) {
return spawn(function* () {
// ...
});
}
// spawn 函数实现
function spawn(genF) {
// async函数返回Promise对象
return new Promise(function(resolve, reject) {
// 创建迭代器
const gen = genF();
function step(nextF) {
let next;
try {
next = nextF();
} catch(e) {
return reject(e);
}
if(next.done) {
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v) {
step(function() { return gen.next(v); });
}, function(e) {
step(function() { return gen.throw(e); });
});
}
step(function() { return gen.next(undefined); });
});
}
与其他异步处理方
- 并发多个请求,但同步输出结果
async function logInOrder(urls) {
// 并发读取远程URL
const textPromises = urls.map(async url => {
const response = await fetch(url);
return response.text();
});
// 按次序输出
for (const textPromise of textPromises) {
console.log(await textPromise);
}
}
Module 模块
基础
- CommonJS模块方式
let { stat, exists, readFile } = require('fs');
这种方式使用的是'运行时加载'加载模式,只有在代码运行时才会去获取执行。这导致没办法在
在编译时做静态检查并优化。
- ES6 Module
新增加的模块不是对象,ES6 模块不是对象,而是通过export命令显式指定输出的代码,再通过import命令输入。
import { stat, exists, readFile } from 'fs';
上面代码的实质是从fs模块加载 3 个方法,其他方法不加载。这种加载称为
“编译时加载”或者静态加载,即 ES6 可以在编译时就完成模块加载,效率
要比 CommonJS 模块的加载方式高。
export
var b = 1;
export {a as b}
export与import复合使用
export {a as b, c} from 'test'
export * from 'test1' // 模块继承
export var a = 1;
严格模式
ES6 的模块自动采用严格模式。
严格模式主要有以下限制。
- 变量必须声明后再使用
- 函数的参数不能有同名属性,否则报错
- 不能使用with语句
- 不能对只读属性赋值,否则报错
- 不能使用前缀 0 表示八进制数,否则报错
- 不能删除不可删除的属性,否则报错
- 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
- eval不会在它的外层作用域引入变量
- eval和arguments不能被重新赋值
- arguments不会自动反映函数参数的变化
- 不能使用arguments.callee
- 不能使用arguments.caller
- 禁止this指向全局对象(6 模块之中,顶层的this指向undefined,即不应该在顶层代码使用this。)
- 不能使用fn.caller和fn.arguments获取函数调用的堆栈
- 增加了保留字(比如protected、static和interface)
编程风格
eslint
使用eslint模块,进行语法规则和代码风格的检查。
常用代码语法规则
- eslint-config-airbnb
- eslint-plugin-import(插件)
- eslint-plugin-jsx-a11y(插件)
- eslint-plugin-react(插件)
.eslintrc
{
"extends": "eslint-config-airbnb"
}