您的位置:首页 > 其它

浅尝ECMAScript6

2016-01-12 13:38 239 查看

浅尝ECMAScript6

简介

ECMAScript6是最新的ECMAScript标准,于2015年6月正式推出(所以也称为ECMAScript2015),相比于2009年推出的es5,es6定义了更加丰富的语言特性,基于该标准的Javascript语言也迎来了语法上的重大变革。本文列举了部分es6新特性,希望之前没接触es6的小伙伴读完本文能对下一代js编程有一个初步的认识。

箭头函数

箭头函数用"=>"简化函数定义,类似于C#,Java8中的Lambda表达式,支持语句块和表达式函数体,和普通函数的唯一区别在于函数体引用的this和包裹代码的this一致。

//表达式
varodds=evens.map(v=>v+1);
varnums=evens.map((v,i)=>v+i);
varpairs=evens.map(v=>({even:v,odd:v+1}));

//代码块
nums.forEach(v=>{
if(v%5===0)
fives.push(v);
});

//this,这里this引用leon
varbob={
_name:"leon",
_friends:[],
printFriends(){
this._friends.forEach(f=>
console.log(this._name+"knows"+f));
}
}


ES6的类简单而言只是基于原型继承的语法糖,使用方便的声明式定义,使得类型定义和其他面向对象语言一致。类支持原型继承,父类调用,实体和静态方法以及构造函数。

'usestrict'

classAnimal{
constructor(name){
this.name=name;
}

speak(msg){
console.log(`${this.name}says${msg}`);
}

staticfight(a,b){
console.log(`${a.name}and${b.name}arefighting!`);
}

}

classDogextendsAnimal{
constructor(name){
super('DOG'+name);
}
}

letdogA=newDog('foo');
letdogB=newDog('bar');

dogA.speak('hi');
dogB.speak(`what'sup`)
Animal.fight(dogA,dogB);

/**
*DOGfoosayshi
*DOGbarsayswhat'sup
*DOGfooandDOGbararefighting!
*/


增强的对象字面量

对象字面量现在支持在对象构建时设置原型对象,定义方法,调用父类构造函数,以及用表达式计算属性.这些特性使得对象字面量定义和类型定义十分相似,给基于对象的设计带来了便利。

varobj={
//原型对象
__proto__:theProtoObj,
//简化定义成员,‘handler:handler’
handler,
//方法
toString(){
//父类调用
return"d"+super.toString();
},
//动态属性名
['prop_'+(()=>42)()]:42
};


模板字符串

模板字符串提供了一种构建字符串的语法糖,类似于Perl,Python和其他语言中的字符串插值特性.

//多行字符串
`InJavaScriptthisis
notlegal.`

//字符串插值
varname="Leon",time="today";
`Hello${name},howareyou${time}?`


解构赋值

解构赋值允许你使用类似数组或对象字面量的语法将数组和对象的属性赋给各种变量。这种赋值语法极度简洁,同时还比传统的属性访问方法更为清晰。

//数组a=1,b=2,c=3
var[a,b,c]=[1,2,3];

//数组,没有匹配的返回undefined,a=1,b=2,c=undefined
var[a,b,c]=[1,2];

//对象,m='leon',n=18
var{name:m,age:n}={name:'leon',age:18}

//对象属性名与变量名一致时,可以简写为
var{foo,bar}={foo:'1',bar:2}

//嵌套name='leon'
var{x:{y:{z:name}}}={x:{y:{z:'leon'}}}


默认参数和不定参数

函数调用者不需要传递所有可能存在的参数,没有被传递的参数由默认参数进行填充。在所有函数参数中,只有最后一个才可以被标记为不定参数。函数被调用时,不定参数前的所有参数都正常填充,任何“额外的”参数都被放进一个数组中并赋值给不定参数。如果没有额外的参数,不定参数就是一个空数组,它永远不会是undefined。

//默认参数
functionf(x,y=12){
//如果没有传入y或传入的值为undefined,则y=12
returnx+y;
}
f(3)==15
//不定参数
functionf(x,...y){
//y是一个数组
returnx*y.length;
}
f(3,"hello",true)==6
functionf(x,y,z){
returnx+y+z;
}
//数组中的每个元素作为参数传入
f(...[1,2,3])==6


let+const块级作用域变量

let和const声明的变量具有块级作用域,传统使用var申明的变量在整个函数内都可访问。const声明的变量只可以在声明时赋值,不可随意修改,否则会导致SyntaxError(语法错误)。

functionf(){
{
letx;
{
constx="me";
//因为是const,所以不可修改,报错
x="foo";
}
//报错,用let重定义变量会抛出一个语法错误
letx="inner";
}
}


迭代器和for..of

迭代器类似于.NETCLR的IEnumerable或Java的Iterable,所有拥有[Symbol.iterator]的对象被称为可迭代的,而for..of用于遍历实现了迭代器方法的对象,比如Array,Map,Set,Array-likeObject

for(varvalueof[1,2,3]){
//依次打印1,2,3
console.log(value);
}


生成器

生成器对象由生成器函数(function*定义的函数)返回,它同时准守iterator和Iterable协议。著名的koanodejs框架就是基于此特性构建。

'usestrict'

function*gen(i){
yieldi+1;
yieldi+2;
}

function*gen1(i){
yieldi;
yield*gen(i);//delegatetogen,aftergenfinished,delegatebackandcontinue
yieldi+3;

return'finished';
}

letg=gen1(10);//gisageneratorobject
console.log(g.next().value);//10
console.log(g.next().value);//11
console.log(g.next().value);//12
console.log(g.next().value);//13
console.log(g.next().value);//finished
console.log(g.next().value);//undefined




模块

模块已经得到语言级别的支持,ES6的模块设计参照了AMDCommonJS规范。

//lib/math.js
//export定义要导出的对象
exportfunctionsum(x,y){
returnx+y;
}
exportvarpi=3.141593;

//没加export,所以foo不被导出
functionfoo(){}
//app.js
//导入全部在lib/math.js中标记为导出的对象
import*asmathfrom"lib/math";
alert("2π="+math.sum(math.pi,math.pi));
//otherApp.js
//显示标记需要导入的成员
import{sum,pi}from"lib/math";
alert("2π="+sum(pi,pi));
//lib/mathplusplus.js
//导入lib/math中的全部对象并重新导出
export*from"lib/math";
exportvare=2.71828182846;
//默认导出对象
exportdefaultfunction(x){
returnMath.log(x);
}
//app.js
//ln为上面的默认导出对象,pi来自于lib/math,e来自于mathplusplus
importln,{pi,e}from"lib/mathplusplus";
alert("2π="+ln(e)*pi*2);


Map+Set+WeakMap+WeakSet

//Sets
vars=newSet();
s.add("hello").add("goodbye").add("hello");
s.size===2;
s.has("hello")===true;

//Maps
varm=newMap();
m.set("hello",42);
m.set(s,34);
m.get(s)==34;

//WeakMaps
varwm=newWeakMap();
wm.set(s,{extra:42});
wm.size===undefined

//WeakSets
varws=newWeakSet();
ws.add({data:42});


Symbol

Symbol是es6新添加的一个基元数据类型,其他的基元类型有string,number,boolean,null,undefined.Symbol是唯一的,一般用作对象的key以存取相关状态信息。

'usestrict'

//Asymbolisauniqueandimmutabledatatypeandmaybeusedasanidentifierforobjectproperties.
//Symbol([description])
lets1=Symbol();
lets2=Symbol('hi');
lets3=Symbol('howareyou');

letobj={[s1]:18};//need[]towrap
obj[s2]="hello";
console.log(obj[s1]);//18
console.log(obj[s2]);//hello

obj[s3]=`I'mfine,thankyou`;

for(letsofObject.getOwnPropertySymbols(obj)){
/**
Symbol()
Symbol(hi)
Symbol(howareyou)
**/
console.log(s);
}

varar=Object.getOwnPropertySymbols(obj);
console.log(ar.length);//3


子类化内置对象

ES6中的内置对象,比如Array,Date等可以被子类继承

//这里定义一个Array的子类MyArray
classMyArrayextendsArray{
constructor(...args){super(...args);}
}


Math+Number+String+Array+Object新增的方法和属性

Number.EPSILON
Number.isInteger(Infinity)//false
Number.isNaN("NaN")//false

Math.acosh(3)//1.762747174039086
Math.hypot(3,4)//5
Math.imul(Math.pow(2,32)-1,Math.pow(2,32)-2)//2

"abcde".includes("cd")//true
"abc".repeat(3)//"abcabcabc"

Array.from(document.querySelectorAll('*'))//返回一个真实的数组
[1,2,3].find(x=>x==3)//3
[1,2,3].findIndex(x=>x==2)//1
["a","b","c"].keys()//iterator0,1,2
["a","b","c"].values()//iterator"a","b","c"

Object.assign(Point,{origin:newPoint(0,0)})


二进制和八进制字面量

//二进制
0b111110111===503//true

//八进制
0o767===503//true


Promises

Promise是异步编程的一种规范,解决了js异步编程中callbackhell问题,在es6中原生支持.

'usestrict'

letp=newPromise(function(resolve,reject){
setTimeout(function(){
resolve(1);
},100);
});

p.then(function(v){
console.log(`thepreviousfunctionreturned${v}`);
});

Promise.resolve(1).then(function(v){
console.log(v);//1
}).catch(function(r){
console.log(r);
});

Promise.reject('failed-leon').then(function(v){
console.log(v);
}).catch(function(r){
console.log(r);//failed-leon
});

Promise.reject('failed').then(function(v){
console.log(v);
},function(r){
console.log(r+'0');//failed0
}).catch(function(r){
console.log(r+'1');//notexecuted
});

//Returnsapromisethateitherresolveswhenallofthepromisesintheiterableargumenthaveresolvedorrejectsassoonasoneofthepromisesintheiterableargumentrejects.Ifthereturnedpromiseresolves,itisresolvedwithanarrayofthevaluesfromtheresolvedpromisesintheiterable.Ifthereturnedpromiserejects,itisrejectedwiththereasonfromthepromiseintheiterablethatrejected.Thismethodcanbeusefulforaggregatingresultsofmultiplepromisestogether.
Promise.all([Promise.resolve(1),Promise.resolve(2),Promise.resolve(3)]).then(function(vs){
for(letvofvs){
console.log(v);//123
}
});

//Returnsapromisethatresolvesorrejectsassoonasoneofthepromisesintheiterableresolvesorrejects,withthevalueorreasonfromthatpromise.
Promise.race([Promise.resolve('a'),Promise.resolve('b'),Promise.resolve('c')]).then(function(v){
console.log(v);//a
});




结语

除了以上特性,es6还增强了对unicode编码的支持,以便更好的支持应用国际化,还有代理等等特性,这里就不一一列举了,目前javascript开发范围越来广泛,web,移动应用,智能家居...2015年中旬es6规范正式推出,尽管当前各厂商浏览器js引擎对es6还没有完全支持,但是新版的nodejs已经默认支持了大部分es6特性,而且我们还可以利用babel将es6编译成es5供浏览器端使用。另外对于.net/java程序员而言,新增的es6特性无需费多大力气就可以熟悉,所以还没有开始接触es6的小伙伴现在可以投入es6的怀抱,用js去改变世界了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: