ES6新特性简介

ES6新特性简介

环境安装

npm install -g babel
npm install -g babel-node  //提供基于node的REPL环境
//创建 .babelrc 文件
{"presets": ["es2015"]}
npm install babel-presets-es2015

箭头函数和词法this

箭头函数的用法类似phython, coffeeScriptjava8

//expression func body, (仅有1参数 括号可省略)
var odds = evens.map(v => v+1);
var nums = evens.map((v,i) => v + i);

//statement func body
nums.forEach( v => {
	if(v % 5 === 0){
		fives.push(v);
	}
});


//lexical this
var sindy = {
	name: 'Sindy',
	friends: ['nami', 'robin'],
	printFriends() {
		//sindy.printFriends() this指向sindy,
		//forEach迭代函数内部this,跟它定义的上下文this一致
		this.friends.forEach(f=>{
			console.log(this.name + ' knows ' + f);
		});
	}
};

类和继承

classextend 是一种语法糖,也是基于原型继承实现的。
class支持 super calls, 实例化,静态方法和构造函数。

class关键字 声明类

//class声明类 内部直接是属性和方法 不用,分隔。 constructor
class Person{
  constructor(name, age){
    this.name = name;//实例属性
    this.age = age;
    
  }
 
 sayhi(name){//原型对象的方法
   console.log(this.name+' say hello to ' + name);
 }
 
 static like(){//静态方法
   console.log('i want to be freedom king');
 }
}

extends关键字 声明继承

//继承关键字 extends
class Zoro extends Person{

  constructor(fav){
  	super('zoro', 18); //constructor中, super引用父类的构造函数

    this.fav = 'keep going';

  	// console.log(super); //error 不能直接打印super 
  	console.log(super('cici',9),'<--c');

  }
  
  sayhi(){
  	// console.log(super); //error 不能直接打印super
  	console.log(super.sayhi(),'<--m'); //原型对象的方法中, super引用父类的原型对象
  	
    super.sayhi();//调用父类原型对象的方法
  }
}

增强的对象字面量

书写对象字面量更方便简洁。 如:foo:foo的简写, 函数定义简写, 动态属性名。

var obj = {
	__proto__: theProtoObj, //设置原型对象
	['__proto__']: somethingElse, //['__proto__']表示计算的属性名,不会认为是设置原型对象, 有时也可避免提早报同名属性的错误
	handler,  // hanlder: handler 的简写
	toString(){//类似定义类 命名函数表达式的名称作为key
		//super calls
		return 'd' + super.toString(); //super 应该指向 theProtoObj
	},
	['prop_'+(()=>23)]: 23 //[expression] 中括号表示内部为属性名的计算表达式,可实现动态属性名
}

__proto__属性在node下都支持,但在浏览器环境不一定都支持, chrome是支持的。

模板字符串

模板字符串跟php双引号字符串类似 "hello ,$name",字符串中可以解析变量和语句, 对于构造字符串是很方便的。

//单行
`this is an alone night`

//多行
`In ES5 this is
not legal`

//变量插值
var name = 'idle', time='today';
var greeting = `hello ${name}, how are you ${time}`;

//不转义
String.raw`in es5 "\n" is a line-feed`

解构

参数解构 对象解构 数组解构, 解构是一种十分方便的语法特性. 当结构不对应解析失败时,会对应的返回undefined,不报错.

//解构赋值
var [a, b] = [1,2]; // a===1, b===2

var {name, age}  = getPerson();

//参数解构
function hello({name: x}){
	console.log('hello, ', x);
}
hello({name: 'alice'});

//解构失败
var [a] = []; // a===undefined

//提供解构失败时的默认值
var [a=1] = []; //a===1 

//参数解构失败的默认值
function r({x,y,w=10,h=20}){
	return x+y+w+h;
}
r({x:1, y:2});

//参数默认值
function f(a, b=10){
	return a+b;
}
f(5);

//rest arguments
function f(x,...y){//剩余形参
	// y is an array
	return x * y.length
}

f(3, 'hello', true);//6

function f(x,y,z){
	return x+y+z;
}

f(...[2,3,4]); //=>9 剩余实参

块级作用域

letconst 声明的变量和常量都是属于块级作用域的.

function f(){
	let x;
	{
		const x = 'sindy'; //ok 因为块级作用域
		x = 'foo'; //error 因为x是常量
	}
	x = 'bar'; //在let 之后赋值,没问题
	let x = 'inner'; //error 重复声明
}

迭代对象(iterator) 和 for .. of ..

迭代对象允许自定义迭代方式,如:

let fibonacci = {
	[Symbol.iterator]() {
		let pre=0, cur=1;
		return {//返回包含next方法的迭代对象(iterator)
			next(){
				[pre, cur] = [cur, pre+cur];
				return {done: false, value: cur}; //iteratorResult
			}
		}
	}
};

for(var n of fibonacci){
	if(n>100){//若无终止条件会一直迭代下去 n应该代表的是每次迭代的结果
		break;
	}
	console.log(n);
}

//typescript风格的iterator接口定义
interface IteratorResult{
	done: boolean,
	value: any
}

interface Iterator {
	next(): IteratorResult //包含next方法,且next()返回IteratorResult类型结果
}

interface Iterable {
	[Symbol.iterator](): Iterator // fibonacci() 执行后返回Iterator
}

生成器generators

function*yield, function*声明的函数返回一个generator实例. generator是iterator的子类型,它包含自己的thrownext

generator可以实现await风格的异步编程

//generator版的fibonacci
var fibonacci = {
	[Symbol.iterator]: function*() {//function*声明
		var pre=0, cur=1;
		for(;;){//不会终止的循环?
			var temp = pre;
			pre = cur;
			cur += pre;
			yield cur;//generator实例每次执行都从yield的地方重新开始?
		}
	}
};

for(var n of fibonacci){
	if(n > 100){
		break;
	}
	console.log(n);
}

//typescript风格的generator接口定义
interface generator extends iterator {
	next(value?: any): IteratorResult; //next方法可带参数, yield返回参数给next?
	throw(exception: any); 
}

注意 iterator and generator 目前需要polyfill才能使用, 新版的chrome已支持.

unicode的完全支持

// same as ES5.1
"𠮷".length == 2

// new RegExp behaviour, opt-in ‘u’
"𠮷".match(/./u)[0].length == 2

// new form
"\u{20BB7}" == "𠮷" == "\uD842\uDFB7"

// new String ops
"𠮷".codePointAt(0) == 0x20BB7

// for-of iterates code points
for(var c of "𠮷") {
  console.log(c);
}

模块(modules)

ES6有不同于amdcmd 的模块风格

//>lib/math.js
export function sum(x,y){
	return x + y;
}

export var fnum = 3.122323;

//>app.js
import * as math from 'lib/math';
console.log(math.sum, math.fnum);

//>other.js
import {fnum, sum} from 'lib/math'; //对象解构赋值
console.log(fnum, sum);

一些额外的特性 export defaultexport *

//>lib/otherMath.js
export * from 'lib/math'; //导出math.js的接口
export var e = 2.323;
export default function(x){
	return Math.exp(x);
}

//>app.js
import exp, {sum , e} from 'lib/otherMath';

模块导出 export

var name = 'sindy';
var age = 20;

//相当于node  module.exports = {name:name, age:age};
export {name, age};

//相当于module.exports.default = function getName(){..}
export default function getName(){
	return name;
}

模块导入 import

//import m from './modA';  m === modA.export.default

//import {name, age} from './modA' modA.exports 析构

import getName, {name, age} from './module-e.es';

console.log(name, age);
console.log(getName());

Map , Set, WeakMap, WeakSet

//Sets
var s = new Set();
s.add('hello').add('goodbye').add('hello');//已有则不再加入
s.size === 2; //true

//Maps
var m = new Map();
m.set('hello', 'good');
m.set(s, 23);
m.get(s) === 23;

//WeakMap
var wm = new WeakMap();
wm.set(s, {extra:24});
vm.size === undefined;

//WeakSet
var ws = new WeakSet();
ws.add({data:12});

proxies

拦截或代理对象的属性读写,函数的调用。

//proxy a normal object
var target = {};//被代理的对象
var handler = {//代理哪些方法
	get: function(reciever, name){//get代理对属性的访问
		return `hello, ${name}`;
	}
};
var p = new Proxy(target, handler);
p.world === 'hello, world';

//proxy a function object
var target = function(){ console.log('i am the target'); };
var handler = {
	apply: function(reciever,...args){//代理 target()
		console.log('i am the proxy');
	}
};


//代理的类型
var handler = {
	//target.prop
	get: ...,
	//target.prop = val
	set: ...,
	//prop in target
	has: ...,
	//delete target.prop
	deleteProperty: ...,
	//target(args)
	apply: ...,
	//new target(args)
	constructor: ...,
	//Object.getOwnPropertyDescriptor(target, prop)
	getOwnPropertyDescriptor: ...,
	//Object.defineProperty(target, prop, descriptor)
	defineProperty: ...,
	//Object.getPrototypeOf(target), target.__proto__
	//obj.isPrototypeOf(target), obj2 instanceof target
	getPrototypeOf: ...,
	//Object.setPrototypeOf(target, proto)
	setPrototypeOf: ...,
	//for(var i in target)
	enumerate: ...,
	//Object.keys(target)
	ownKeys: ...,
	//Object.preventExtensions(target)
	preventExtensions: ...,
	//Object.isExtensible(target)
	isExtensible: ...
}

标识符 symbol

(function(){
	//module scope symbol
	var key = Symbol('key');

	function MyClass(privateData){
		this[key] = privateData;
	}
	MyClass.prototype = {
		dostuff: function(){
			...this[key]..
		}
	};

	typeof key === 'symbol';
})();

var c = new MyClass();
c['key'] === undefined;

内置的子类

Array , DateElement等成为内置的子类。

class MyArray extends Array{
	constructor(...args){
		super(...args);
	}
}

var arr = new MyArray();
arr[1] = 12;
arr.length === 2;

Math + Number + String + Object API扩展

Number.isInterger(Ifinity); //false
Number.isNaN('NaN'); //false

Math.hypot(3,4); //5

'abcde'.includes('abc');
'abc'.repeat(2);

Array.from(document.querySelectAll('h2')); //return a real array
Array.of(1,2,3); => [1,2,3] 枚举数组元素的形式 创建数据, 同 new Array(1,2,3); 但没有仅有1各参数时的歧义
[0,0,0].fill(7,1); //从index==1开始填充7
[1,2,3].findIndex(x=>x==2); //返回使迭代器为真的元素的索引
['a','b','c'].entries(); //iterator [0,'a'], [1,'b'], [2, 'c']
['a','b','c'].keys(); //iterator 0,1,2
['a','b','c'].values(); //iterator 'a','b','c'

var alice = {name: 'Alice'};
Object.assign(alice, {age: 18}); //类似extend

二进制和八进制字面量

0b111110111 === 503
0o767 === 503

Promises

Promise是一个异步编程的库,存在于很多其他的JS库中

function timeout(duration = 0){
	return new Promise((resolve, reject) => {//返回稍后将被resolve的promise对象
		setTimeout(resolve, duration);//定时resolve这个新new的promise
	});
}

var p = timeout(1000).then(()=>{//promise链
	return timeout(2000);
}).then(()=>{
	throw new Error('test');
}).catch(err=>{
	return Promise.all([timeout(100), timeout(200)]);
});

反射API(Reflect API)

var o = {a: 1};
Object.defineProperty(o, 'b', {value:2});
o[Symbol('c')] = 3;

Reflect.ownKeys(o); //['a','b',Symbol(c)]

function C(a,b){
	return this.c = a + b;
}
var instance = Reflect.construct(C, [10,12]);
instance.c === 22;

尾调用 tail calls

防止stack overflow

function factorial(n, acc=1){//阶乘计算
	'use strict';
	if(n <= 1){ return acc; }
	return factorail(n-1, n*acc);
}

factorail(10000); //尾调用优化后不会 stack overflow
posted @ 2016-06-25 18:38  stephenykk  阅读(3421)  评论(0编辑  收藏  举报