ECMAScript 6 新特性分析.docx
- 文档编号:24229092
- 上传时间:2023-05-25
- 格式:DOCX
- 页数:18
- 大小:22.89KB
ECMAScript 6 新特性分析.docx
《ECMAScript 6 新特性分析.docx》由会员分享,可在线阅读,更多相关《ECMAScript 6 新特性分析.docx(18页珍藏版)》请在冰豆网上搜索。
ECMAScript6新特性分析
ECMAScript6新特性
箭头函数和静态this(ArrowsandLexicalThis)
箭头函数使用胖箭头(=>)语法,与C#,Java8和CoffeeScript类似。
支持表达式和语句作为函数体。
不像普通函数,箭头函数的this是和文法作用域绑定的。
//表达式作为函数体
varodds=evens.map(v=>v+1);
varnums=evens.map((v,i)=>v+i);
//语句作为函数体
nums.forEach(v=>{
if(v%5===0)
fives.push(v);
});
//静态this
varbob={
_name:
"Bob",
_friends:
[],
printFriends(){
this._friends.forEach(f=>
console.log(this._name+"knows"+f));
}
};
类(Classes)
ES2015中的类是对基于原型面向对象模式的一个简单语法糖。
有一个单一的声明形式可以使类模式更容易使用,并鼓励互操作性。
类支持基于原型的继承,超类调用(super),实例方法,静态方法和构造函数。
classSkinnedMeshextendsTHREE.Mesh{
constructor(geometry,materials){
super(geometry,materials);
this.idMatrix=SkinnedMesh.defaultMatrix();
this.bones=[];
this.boneMatrices=[];
//...
}
update(camera){
//...
super.update();
}
staticdefaultMatrix(){
returnnewTHREE.Matrix4();
}
}
增强对象字面量(EnhancedObjectLiterals)
对象字面量被扩展支持直接设置原型,简洁属性赋值和方法,超类调用。
这也让对象字面量和类声明的关系更密切,并让基于对象的设计更便利。
varobj={
//__proto__
__proto__:
theProtoObj,
//下面的写法不会设置内部原型
'__proto__':
somethingElse,
//‘handler:
handler’的简写
handler,
//方法
toString(){
//调用父对象的方法
return"d"+super.toString();
},
//属性名是一个表达式
["prop_"+(()=>42)()]:
42
};
__proto__属性需要原生支持,这一属性在ECMAScript前一个版本中一度被废弃。
目前为止,大部分引擎支持这一属性。
同时需要注意,仅仅web浏览器需要实现这一属性,在Node中现在就可使用。
模版字符串(TemplateStrings)
模版字符串提供构建字符串的语法糖。
这类似Perl,Python等其他语言中的字符串插值。
可以选择性添加一个标签,允许对字符串构建的定制化,避免注入攻击或其他需求。
//普通字符串
`Thisisaprettylittletemplatestring.`
//多行字符串
`InES5thisis
notlegal.`
//字符串中嵌入变量
varname="Bob",time="today";
`Hello${name},${time}?
`
//模版标签
String.raw`InES5"\n"isaline-feed.`
//下面构造一个HTTP请求头,来解释差值替换和构造
GET`http:
//foo.org/bar?
a=${a}&b=${b}
Content-Type:
application/json
X-Credentials:
${credentials}
{"foo":
${foo},
"bar":
${bar}}`(myOnReadyStateChangeHandler);
解构(Destructuring)
按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
解构失败是静默的,类似标准的对象属性查找foo[“bar”],找不到值则为undefined。
//列表匹配
var[a,,b]=[1,2,3];
//对象匹配
var{op:
a,lhs:
{op:
b},rhs:
c}
=getASTNode()
//对象匹配简写
//绑定作用域中的`op`,`lhs`和`rhs`
var{op,lhs,rhs}=getASTNode()
//函数参数
functiong({name:
x}){
console.log(x);
}
g({name:
5})
//解构失败,赋值为undefined
var[a]=[];
a===undefined;
//如果有默认值,则为默认值
var[a=1]=[];
a===1;
默认值+Rest参数+扩展运算符(Default+Rest+Spread)
现在函数调用可以传递默认参数了;扩展运算符允许将数组转化为函数的参数传入;rest参数,用于获取函数的多余参数,这样就不需要使用arguments对象了。
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类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
const也用来声明变量,但是声明的是常量。
一旦声明,常量的值就不能改变。
functionf(){
{
letx;
{
//块作用域
constx="sneaky";
//const常量重新赋值会报错
x="foo";
}
//let变量可以再次赋值
x="bar";
//在块作用域中重复声明将会报错
letx="inner";
}
}
Iterator和for..of循环(Iterators+For..Of)
遍历器对象能够自定义遍历行为,这很像Java的Iterable。
新增的for..of用来代替for..in。
并不需要是数组,任何数据结构只要部署Iterator接口,就可以完成遍历操作。
letfibonacci={
[](){
letpre=0,cur=1;
return{
next(){
[pre,cur]=[cur,pre+cur];
return{done:
false,value:
cur}
}
}
}
}
for(varnoffibonacci){
if(n>1000)
break;
console.log(n);
}
遍历器基于弱类型接口(下面是使用TypeScript语法的展示):
interfaceIteratorResult{
done:
boolean;
value:
any;
}
interfaceIterator{
next():
IteratorResult;
}
interfaceIterable{
[Symbol.iterator]():
Iterator
}
需要腻子脚本(Supportviapolyfill)
使用遍历器需要引用Babel腻子脚本。
Generator函数(Generators)
Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
Generator函数有多种理解角度。
从语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。
返回的遍历器对象,可以依次遍历Generator函数内部的每一个状态。
形式上,Generator函数是一个普通函数,但是有两个特征。
一是,function命令与函数名之间有一个星号;二是,函数体内部使用yield语句,定义不同的内部状态(yield语句在英语里的意思就是“产出”)。
注意:
也可以使用‘await’——类似异步编程,参见ES7await 提案。
varfibonacci={
[Symbol.iterator]:
function*(){
varpre=0,cur=1;
for(;;){
vartemp=pre;
pre=cur;
cur+=temp;
yieldcur;
}
}
}
for(varnoffibonacci){
//截断1000以后的数据
if(n>1000)
break;
console.log(n);
}
generator接口原理如下(使用TypeScript语法的模拟):
interfaceGeneratorextendsIterator{
next(value?
:
any):
IteratorResult;
throw(exception:
any);
}
需要腻子脚本(Supportviapolyfill)
为了使用Generator,需要引用Babel的腻子脚本。
Unicode
ES6增强了对Unicode的支持,包括新的unicode字面量和新的正则匹配参数u模式,以及新的API来处理超过两个字节的字符。
//ES5.1中
"��".length==2
//新的正则参数u
"��".match(/./u)[0].length==2
//新的表示法
"\u{20BB7}"=="��"=="\uD842\uDFB7"
//新字符串方法
"��".codePointAt(0)==0x20BB7
//for-of
for(varcof"��"){
console.log(c);
}
模块(Modules)
语言级支持定义模块和组件。
新模块的设计汇总了流行JavaScript模块加载器(AMD,CommonJS)的优点。
模块的实现机制由运行时环境实现。
隐式异步模型——模块加载完成之前代码不会执行。
//lib/math.js
exportfunctionsum(x,y){
returnx+y;
}
exportvarpi=3.141593;
//app.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
export*from"lib/math";
exportvare=2.71828182846;
exportdefaultfunction(x){
returnMath.exp(x);
}
//app.js
importexp,{pi,e}from"lib/mathplusplus";
alert("2π="+exp(pi,e));
模块格式化
Babel可以将ES2015的模块转译成几种不同的模块格式,包括Common.js,AMD,System和UMD。
你甚至可以创建自己的模块格式,更多细节可以查看模块的文档。
Map+Set+WeakMap+WeakSet
专为常见算法设计的高效数据结构。
WeakMaps提供对象的弱引用作为键名的索引表。
//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});
//Becausetheaddedobjecthasnootherreferences,itwillnotbeheldintheset
需要使用polyfill
为了使用这些新数据结构,你必须引入babel的腻子脚本。
代理(Proxies)
Proxy可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
//代理对象
vartarget={};
varhandler={
get:
function(receiver,name){
return`Hello,${name}!
`;
}
};
varp=newProxy(target,handler);
p.world==="Hello,world!
";
//代理函数
vartarget=function(){return"Iamthetarget";};
varhandler={
apply:
function(receiver,...args){
return"Iamtheproxy";
}
};
varp=newProxy(target,handler);
p()==="Iamtheproxy";
下面是Proxy支持的拦截操作一览:
varhandler=
{
//target.prop
get:
...,
//target.prop=value
set:
...,
//'prop'intarget
has:
...,
//deletetarget.prop
deleteProperty:
...,
//target(...args)
apply:
...,
//newtarget(...args)
construct:
...,
//Object.getOwnPropertyDescriptor(target,'prop')
getOwnPropertyDescriptor:
...,
//Object.defineProperty(target,'prop',descriptor)
defineProperty:
...,
//Object.getPrototypeOf(target),Reflect.getPrototypeOf(target),
//target.__proto__,object.isPrototypeOf(target),objectinstanceoftarget
getPrototypeOf:
...,
//Object.setPrototypeOf(target),Reflect.setPrototypeOf(target)
setPrototypeOf:
...,
//for(letiintarget){}
enumerate:
...,
//Object.keys(target)
ownKeys:
...,
//Object.preventExtensions(target)
preventExtensions:
...,
//Object.isExtensible(target)
isExtensible:
...
}
不支持的特性(Unsupportedfeature)
由于ES5的局限性,Proxy不能被转换和填补。
Symbols
Symbol可以作为对象的键值,是一种新的原始类型。
Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
Symbol是独一无二的,但可以通过Object.getOwnPropertySymbols获取到。
(function(){
//块级作用域
varkey=Symbol("key");
functionMyClass(privateData){
this[key]=privateData;
}
MyC={
doStuff:
function(){
...this[key]...
}
};
//Babel不能支持下面的操作,需要原生支持
typeofkey==="symbol"
})();
varc=newMyClass("hello")
c["key"]===undefined
需要腻子脚本(不完备)(Limitedsupportviapolyfill)
需要使用Babel的腻子脚本,但无法全部支持。
由于语言的限制,有些特性无法被转义和填补。
更多细节请查看core.js的相关说明。
继承内建父类(SubclassableBuilt-ins)
在ES2015中,语言内置父类如Array,Date和Dom元素能够被子类继承。
//子类继承Array
classMyArrayextendsArray{
constructor(...args){super(...args);}
}
vararr=newMyArray();
arr[1]=12;
arr.length==2
部分支持(Partialsupport)
能够子类化的父类必须是基于类的,比如HTMLElement能被子类继承,然后由于ES5引擎的限制许多父类不能被子类化,如Date,Array和Error等。
Math+Number+String+ObjectAPIs
ES2015扩展了很多新的API,包括核心数学函数,数组转换接口和实现对象复制功能的Object.assign。
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("*"))//返回一个真正的数组
Array.of(1,2,3)//类似newArray(...),但只有一个参数时语义不变
[0,0,0].fill(7,1)//[0,7,7]
[1,2,3].findIndex(x=>x==2)//1
["a","b","c"].entries()//iterator[0,"a"],[1,"b"],[2,"c"]
["a","b","c"].keys()//iterator0,1,2
["a","b","c"].values()//iterator"a","b","c"
Object.assign(Point,{origin:
newPoint(0,0)})
需要使用腻子脚本(不能完全模拟)(Limitedsupportfrompolyfill)
通过Babel的腻子脚本,能够支持大部分API,然而,由于各种原因(例如,String.prototype.normalize需要添加大量代码)并未全部支持。
你可以点击这里找到更多腻子脚本。
二进制和八进制字面量(BinaryandOctalLiterals)
新增了二进制和八进制字面量表示法(注意和原来的ES5废弃的八进制表示法不同)。
0b111110111===503//true
0o767===503//true
仅支持字面量形式(Onlysupportsliteralform)
Babel仅能转换0o767,不支持Numver("0o767")。
Promises
所谓Promise,就是一个对象,用来传递异步操作的消息。
它代表了某个未来才会知道结果的事件(通常是一个异步操作),并且这个事件提供统一的API,可供进一步处理。
目前JavaScript库已在使用中。
functiontimeout(duration=0){
returnnewPromise((resolve,reject)=>{
setTimeout(resolve,duration);
})
}
varp=timeout(1000).then(()=>{
returntimeout(2000);
}).then(()=>{
thrownewError("hmm");
}).catch(err=>{
returnPromise.all([timeout(100),timeout(200)]);
})
需要使用腻子脚本(Supportviapolyfill)
要想使用Promises需要引用Babel腻子脚本。
反射(ReflectAPI)
Reflect对象与Pr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ECMAScript 新特性分析 特性 分析