Open i12n opened 9 years ago
# 安装babel
$ npm install --global babel
#运行支持ES6的REPL环境
$ babel-node
#运行ES6脚本
$ babel-node yourfilename.js
按一定模式,从数组中取值
// 数组解构
let [a, b, c] = [3, 2, 1];
console.log(a); // 3
console.log(b); // 2
console.log(c); // 1
let [x, , y] = [1, 2, 3];
console.log(x); // 1
console.log(y); // 3
let [m, [n], [p]] = [1, [2], [3]];
console.log(m); // 1
console.log(n); // 2
console.log(p); // 3
let [header, ...trail] = [1, 2, 3, 4, 5, 6];
console.log(header); // 1
console.log(trail); //[2, 3, 4, 5, 6]
// 默认值,数组成员为 undefined 时默认值生效
let [ref1 = 1, ref2 = 2, ref3 = 3, ref4 = 4, ref5] = [0, null, undefined];
console.log(ref1); // 0
console.log(ref2); // null
console.log(ref3); // 3
console.log(ref4); // 4
console.log(ref5); // undefined
按一定模式从对象中取出属性和方法
//支持默认值,当对象为 undefined 时,默认值生效
let {a, b, c = 2, d} = {a: 1, b: "one"};
console.log(a); // 1
console.log(b); // "one"
console.log(c); // 2
console.log(d); // undefinded
let x;
({x} = {x:1}); // 避免将 {} 解析为 代码块,要加 (),{x} = {x: 1} 会报错
console.log(x); // 1
Firefox 代码草稿纸
Proxy 可以理解为给对象增加了代理,代理将对象进行包装,在外界使用代理访问对象的同时,可以做一些额外的事情。
// new Proxy(target, handler);
var p = new Proxy( {name: 'Jim'}, {
get: function(target, name) {
console.log(name);
// 返回属性值,以正常访问到对象
return target.name;
},
set: function(target, prop, value) {
if (prop === 'age') {
if (value > 200) {
throw new RangError('The age seem invalid');
}
}
// 设置属性值
target[prop] = value;
}
});
p.name; // name
p.age; // age
p.name = 'Tom';
console.log(p.name); // Tom
p.age = 2001; // ReferenceError
Firefox 代码草稿纸
Set 是一个数据集合,不允许重复的数据
// 使用数组初始化 set
var s = new Set([6, 5]);
// 添加值
s.add(4);
s.add(5); // 出现重复,被忽略
console.log(s.size); // 3
// 判断一个值是否在 set 中,使用 has 方法
console.log(s.has(4)); // true
// 遍历set 使用 for... of
for ( v of s) {
console.log(v); // 6 5 4
}
// 数组去重
var a = [1, 1 ,3, 3];
a = [...(new Set(a))]; // [1, 3]
for...of 遍历属性值 for...in 遍历属性名称
Map 是键值对的集合,虽然对象本质上也是键值对的集合,但是对象只能用字符串当做键。
// 初始化化
var map = new Map([['one', 1], ['two', 2]]);
console.log(map.size); // 2
console.log(map.has('one')); // true
console.log(map.get('one')); // 1
// 遍历 key
for (let key of map.keys()) {
console.log(key); // one two
}
// 遍历 value
for (let value of map.values()) {
console.log(value); // 1 2
}
for (let [key, value] of map) {
console.log([key, value]); // ["one", 1] ["two", 2]
}
[...map.entries()]; // [["one", 1], ["two", 2]]
与 C++ 的迭代器类似,ES6 也提供了 Iterator 接口,用来遍历一些数据结构。
定义一个 Iterator 的方法如下:
// TypeScript
interface IteratorResult {
done: boolean;
value: any;
}
interface Iterator {
next(): IteratorResult;
}
Iterator 是一个对象,定义了用于遍历的 next 方法;next 返回的是一个对象,其中value是遍历的返回值,done表示遍历是否结束。
function myIterator() {
var id = 0;
// 返回 Iterator
return ({
// 定义 next 方法
next() {
if (id < 4) {
return {value: id++, done: false};
} else {
return {done: true};
}
}
});
};
var it = myIterator();
console.log(it.next()); // {value = 0, done = false }
Iterator 的作用是遍历数据结构,为数据结构的访问提供统一的接口,那么如何遍历数据结构呢?首先要将 Iterator 部署到数据结构,部署方法如下:
interface Iterable {
[Symbol.iterator](): Iterator
}
将 Iterator 配置给数据结构的 Symbol.iterator 属性,Symbol.iterator 是一个方法,调用这个方法就会得到 Iterator。
var array = [5,5,5,5,5];
// 为array 配置 Iterator
array[Symbol.iterator] = myIterator;
配置了 Symbol.iterator ,就可以使用 for...of 进行遍历。
for(var i of array) {
console.log(i); // 0 1 2 3
}
一些原生的数据结构(例如Array,Set,Map)已经具备了Iterator接口,因为这些数据结构已经部署了 Symbol.iterator属性。在这里重新部署了 array 的 Symbol.iterator,因此for...of遍历array时没有打印它的元素。
Iterator 是为数据遍历服务的,更确切的说,是为for...of提供支持的;只有配置了Symbol.iterator,才能使用for...of遍历;另外,Object 是不支持 for...of 遍历的,可以使用for...in 。
一个遍历斐波那契数列的代码
var fib = {
[Symbol.iterator]() {
var pre = 0,
cur = 1;
return {
next(){
var tmp = cur;
cur = pre + cur;
pre = tmp;
return {done: false, value: cur};
}
}
}
};
for (var n of fib) {
if (n > 100)
break;
console.log(n);
}
Iterator + for..of ES6 In Depth: Iterators and the for-of loop
function *run(signal) {
var i = 0;
console.log(i);
while(++i){
console.log(i);
if(yield signal) break;
}
}
var worker = run();
worker.next(); // 打印 0 1
worker.next(); // 打印 2
worker.next(true);
worker.next();
Generator 函数主要特点是:
gulp-babel 可以将 es6 转换为 es5 ,这样可以避免浏览器不支持 es6 而带来的问题。
例如以下es6代码:
let a = 3;
alert(a);
被转换为
"use strict";
var a = 3;
alert(a);
gulp-eslint 可用对代码进行格式检测和语法错误检测等。 与 gulp-jshint 相比,gulp-eslint 对 es6 提供支持。由于 gulp-eslint 是可配置的,可以根据需求配置相关规则,并且提供了详细的配置文档。 为了支持 es6 特性,在 package.json 中添加如下配置:
"eslintConfig": {
"env": {
"browser": true,
"node": true,
"es6": true
}
}
如果不添加,在对如下代码进行检测时,将报错:error Parsing error: Unexpected token let
let a = 3;
alert(a);
ES6 class 并没有引入新的面向对象模型,它只是一个方便使用的语法糖,并没有改变已有的基于原型链的面向对象方式。 class 的定义和使用,如下代码:
class Fruit {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
var apple = new Fruit('apple');
apple.sayName(); // apple
class Orange extends Fruit {
constructor(price, weight) {
super('Orange');
this.weight = weight;
this.price = price;
}
sayWeight() {
console.log(this.weight);
}
get total() {
return this.price * this.weight;
}
}
var orange = new Orange(3.14, 2);
orange.sayWeight(); // 2
console.log(orange.total); // 6.28
首先,constructor 在 new 一个实例的过程中会被执行,如果没有实现 constructor 方法,则会生成一个空的constructor方法。
其次,extends 可以实现类继承,super 用于调用父类的 constructor. ES5 和 ES6 在实现继承是存在差别的,ES5 是先创建子类的实例对象,然后将父类的方法添加到 this 上;而 ES6 是先创建父类的实例对象 this 然后子类的构造函数来修改 this.
由Yehuda Katz 提出的 Decorators ,是ES7的一个提案。
Decorators make it possible to annotate and modify classes and properties at design time. A decorator is:
- an expression
- that evaluates to a function
- that takes the target, name, and decorator descriptor as arguments
- and optionally returns a decorator descriptor to install on the target object
Decorators 作为一种语法糖,可以修饰类和类的属性,但是要依赖于 ES5 的 Object.defineProperty。Decorators 修饰属性的时候, 传递的参数 target、 name、 decorator 与 Object.defineProperty 的参数是一致的,target 是类的 prototype。
function setLog(target, name, descriptor) {
let funName = '_' + name;
Object.defineProperty(target, funName, {
value: function() {
console.log('start run ' + name);
target[name]();
console.log(name + ' finish');
}
});
return descriptor;
}
class Apple {
@setLog
showName() {
console.log('apple');
}
}
var apple = new Apple();
apple._showName();
Decorators 也可以修饰类,参数 target 为类的自身。
function isFruit(target) {
target.isFruit = true;
}
@isFruit
class Apple {
}
console.log(Apple.isFruit); // true
目前 babel 支持 decorators,使用方法如下: 命令行:
$ babel --optional es7.decorators source.js > dest.js
脚本:
babel.transform("code", {optional: ["es7.decorators"]})
2017.8.14补充 Decorators 中的参数 target 是 class 的 constructor 或 property,并不是该 class 定义的具体的 object。在下面的代码中,discount 将用于装饰 Apple 类中的 getPrice 方法(discount 将原有的 descriptor.value 重写,也就是 getPrice 函数被重新定义),注意以下几点:
function discount(target, name, descriptor) { // 在 class 的 constructor 执行之前就已经被执行,this 指向全局 window
let method = descriptor.value; // 原有的方法,原有方法中的 this 指向的是class
定义的 object 对象,但是此时 constructor 还没有被执行,所以 这时的 object 为 undefined ,也就是this 为 undefined
descriptor.value = function(...args) { // 重新定义方法, this 指向 class 定义的具体 object,如果这里用箭头函数则 this 为 外部作用域里的 this 也就是 window
let ret = method.apply(this, ...args); // 执行原有方法,需要将原有方法中的 this 指向 具体的 object
return ret * 0.95
}
return descriptor;
}
class Apple {
constructor(price) {
this.price = price;
}
@discount
getPrice() {
return this.price;
}
}
const apple = new Apple(6);
console.log(apple.getPrice());
https://jsfiddle.net/kxokqLh7/ http://www.darul.io/post/2016-02-11_es7-decorators-in-depth-or-not
refer:
String.prototype.includes 判断字符串是否包含某个子串
用法:str.includes(searchString[, position])
, position 为起始位置
返回值: true
false
大小写敏感
console.log('String'.includes('St')); // true
console.log('String'.includes('st')); // false
console.log('String'.includes('st', 1)); // false
Array.prototype.includes 判断数组是否包含某个元素, 更详细的介绍
用法 array.includes(searchElement[, fromIndex])
, fromIndex 为起始位置
返回值:true
false
可以判断 NaN
console.log(['a', 'b'].includes('a')); // true
console.log(['a', 'b'].includes('a', 1)); // false
console.log([NaN].includes(NaN)); // true
Promise 在出现异常的时候,会自动将异常抛给下一级的 reject 函数,而不是本级的 reject 函数,例如下面的代码,并不会将错误信息打印:
var promise = new Promise((resolve, reject) => resolve());
promise
.then(
() => { throw new Error('Resolve Error!!!') },
e => console.log(e)
);
而这段代码则会将错误信息打印:
var promise = new Promise((resolve, reject) => resolve());
promise
.then(
() => { throw new Error('Resolve Error!!!') },
e => console.log(e)
)
.then(
() => {},
e => console.log(e) // 'Resolve Error!!!'
);
为了方便,可以在最后一级的后面加一个 catch 来输出错误信息:
var promise = new Promise((resolve, reject) => resolve());
promise
.then(
() => { throw new Error('Resolve Error!!!') },
e => console.log(e)
)
.catch(
e => console.log(e) // 'Resolve Error!!!'
);
每一层只能捕获上一层的异常,而异常被处理之后,下一层将会恢复正常不会手影响。也就是说,无论异常与否,每一层都会进入直至结束。
var promise = new Promise((resolve, reject) => resolve());
promise
.then(
() => { throw new Error('Resolve Error!!!') },
e => console.log(e)
)
.then(
() => {},
e => console.log(e) // 'Resolve Error!!!'
)
.then(
() => console.log('end'), // 'end'
e => console.log(e)
);
箭头函数没有自己的 this
,它的 this
继承自外围作用域。
运行环境
安装 node,并运行以下命令查看已经实现的ES6特性
运行js文件
let