当前位置: 首页 > 后端技术 > Node.js

[ES6]对象的新功能和解构赋值

时间:2023-04-03 15:57:35 Node.js

ES6通过文字语法扩展、新方法、改进原型等多种方式增强对象的使用,通过解构简化对象的数据提取过程。1、字面量语法扩展ES6模式下使用字面量创建对象更简洁。对于对象属性,属性的初始值可以缩写,可以使用可计算的属性名。对象方法的定义去掉了冒号和function关键字,例子如下://Demo1varvalue="name",age=18varperson={age,//age:age['my'+value]:'Jenny',//mynamesayName(){//sayName:function()console.log(this.myname)}}console.log(person.age)//18console.log(person.myname)//Jennyperson.sayName();//Jenny对于重复定义的对象字面量属性,ES5严格模式会进行重复的属性检查并抛出错误,但是ES6去掉了这个机制,无论严格模式还是非严格模式,同名属性都会取最后一个值。//demo2varperson={['my'+value]:'Jenny',myname:'Tom',myname:'Lee',}console.log(person.myname)//Lee2.新方法从ES5One开始遵循的设计目标之一是避免创建新的全局函数,也不是在object.prototype上创建新方法。为了简化某些任务,ES6在全局Object对象上引入了一些新方法。2.1Object.is()ES6引入了Object.is()方法来弥补恒等运算符计算不准确的问题。比较时相等运算符不触发强制类型,与Object.is()操作结果类似,但对于+0和-0(JS引擎中两个不同的实体)和特殊值NaN的比较结果不同,例如://demo3console.log(5=='5')//trueconsole.log(5==='5')//falseconsole.log(Object.is(5,'5'))//falseconsole.log(+0==-0)//trueconsole.log(+0===-0)//trueconsole.log(Object.is(+0,-0))//falseconsole.log(NaN==NaN)//falseconsole.log(NaN===NaN)//falseconsole.log(Object.is(NaN,NaN))//true综上所述,Object.is()对所有值的等价判断更为严格。当然,是否使用Object.is()而不是相等运算符(===)取决于这些特殊情况是否影响代码。2.2Object.assign()ES6新增Object.assign()实现了混合(Mixin)模式,即一个对象接收另一个对象的属性和方法。注意这里是接收而不是继承,比如demo1中接收对象://demo4varfriend={}Object.assign(friend,person)friend.sayName()//Jennyconsole.log(friend.age)//18console.log(Object.getPrototypeOf(friend)===person)//false在Object.assign()之前,很多JS库都自定义了mixin方法mixin()实现对象组合,代码类似:functionmixin(receiver,supplier){Object.keys(supplier).forEach(function(key){receiver[key]=supplier[key]})returnreceiver}可以看出mixin()方法使用了“=”赋值操作和无法复制访问器属性。Object.assign()不能复制访问器属性,它只是进行赋值操作,访问器属性最终会转化为接收对象的数据属性。这是一个例子://demo5varanimal={name:'lili',gettype(){returnthis.name+type},settype(news){type=news}}animal.type='cat'console.log(animal.type)//lilicatvarpet={}Object.assign(pet,animal)console.log(animal)//{名称:'lili',类型:[Getter/Setter]}console.log(pet)//{name:'lili',type:'lilicat'}2.3Object.setPrototypeOf()一般情况下,原型是在通过构造函数或Object.create()创建时指定的。ES6添加了Object.setPrototypeOf()方法来改变对象的原型。比如创建一个继承person对象的coder对象,然后改变coder对象的原型://demo6letperson={myname:'Jenny',sayName(){console.log(this.myname)}}//将原型创建为person编码器对象,sayName(){console.log(this.myname)}}//将coder对象的原型改为heroObject.setPrototypeOf(coder,hero)coder.sayName()//leeconsole.log(Object.getPrototypeOf(coder)===hero)//true对象原型存储在内部私有属性[[Prototype]]中,调用Object.getPrototypeOf()返回存储在其中的值,调用Object.setPrototypeOf()改变它的值。该方法强化了对对象原型的操作,下一节重点介绍其他操作原型的方式。3.增强的ObjectPrototypePrototype是JS继承的基础。ES6对prototype做了很多改进,目的是为了更灵活的使用prototype。除了新增Object.setPrototypeOf()改变原型外,还引入了Super关键字来简化对原型的访问。3.1Super关键字ES6引入了Super来更方便的访问对象原型。上一节介绍了ES5可以使用Object.getPrototypeOf()返回对象原型。为了说明Super的方便,当对象需要复用原型方法,重新定义自己的方法时,两种实现方式如下://demo7letcoder1={getName(){console.log("coder1name:")Object.getPrototypeOf(this).sayName.call(this)}}//设置coder1对象的原型为hero(demo6)Object.setPrototypeOf(coder1,hero)coder1.getName()//coder1name:leeletcoder2={getName(){console.log("coder2name:")super.sayName()}}Object.setPrototypeOf(coder2,hero)coder2.getName()//coder2name:leecoder1对象的getName方法也需要call(this)保证使用最重要的是原型方法的this,比较复杂,多继承会出现递归调用栈溢出错误,但是直接用super很简单安全.注意速记方法中必须使用Super,否则会报错,例如下面的代码运行语法错误:letcoder4={getName:function(){//getName()是正确的)//SyntaxError:'super'keywordunexpectedhere}因为例子中getName成为匿名函数定义的一个属性,所以在当前上下文中调用Super引用是非法的。不明白的可以仔细看一下方法的从属对象。3.2方法的从属对象在ES6之前,“方法”是一个具有功能的对象属性,而不是数据。ES6将方法正式定义为具有[[HomeObject]]内部属性的函数。[[HomeObject]]属性存放的是当前方法的从属对象,例如:HomeObject")}coder5对象的sayName()方法的[[HomeObject]]属性值为coder5,但是函数定义的shareName()并没有将其赋值给对象,所以其[[HomeObject]]属性未定义,这在使用Super时非常重要。Super是在[[HomeObject]]属性上调用Object.getPrototypeOf()获取原型引用,然后搜索原型获取同名函数,最后设置this绑定调用对应的方法。4、解构赋值ES6为数组和对象字面量提供了一个新的特性——解构,可以简化数据提取的过程,减少同质代码。解构的基本语法示例如下:letuser={name:'jenny',id:18}let{name,id}=userconsole.log(name,id)//jenny18注意这段代码中,user.name存储在与对象属性名同名的name变量中。4.1默认值如果解构时变量名与对象属性名不同,即对象中不存在,则默认为undefined:letuser={name:'jenny',id:18}let{name,id,job}=userconsole.log(name,id,job)//jenny18undefined4.2非同义变量赋值非同义变量的默认值是undefined,但是更多时候需要assigned,对象属性值会被赋值给不相同的变量。ES6为此提供了扩展语法,很像对象文字属性初始值设定项:letuser={name:'jenny',id:18}let{name,id=16,job='engineer'}=userconsole.log(name,id,job)//jenny18engineerlet{name:localName,id:localId}=userconsole.log(localName,localId)//jenny18let{name:otherName='lee',job:otherJob='teacher'}=userconsole.log(otherName,otherJob)//jennyteacher可以看出这个语法其实是相反的对象字面量,赋值名在冒号左边,变量名在右边,解构赋值时,只更新默认值,不会覆盖对象原有的属性值。4.3嵌套解构解构嵌套对象的语法还是类似于对象字面量,使用花括号继续寻找底层结构:letuser={name:'jenny',id:18,desc:{pos:{lng:111,lat:333}}}let{desc:{pos}}=userconsole.log(pos)//{lng:111,lat:333}let{desc:{pos:{lng}}}=userconsole.log(lng)//111let{desc:{pos:{lng:longitude}}}=userconsole.log(longitude)//111五、对象类别ES6规范定义了对象类别,特别是对于浏览器这样的执行环境。普通对象具有JS对象的所有默认内部行为Exotic对象具有一些不符合默认行为的内部行为标准对象ES6规范中定义的对象可以是普通对象也可以是特殊对象,比如Date,Built-inobjects比如Array脚本开始执行时JS执行环境中存在的对象所有标准对象都是内置对象推荐阅读《深入理解ES6》加油吧少年~