当前位置: 首页 > Web前端 > HTML5

深入理解ES6的《扩展对象》

时间:2023-04-05 21:18:27 HTML5

属性初始值的简写当对象字面量只有一个属性名时,JS引擎会在可访问范围内寻找一个同名的变量;如果找到,变量的值将被分配给对象字面量中具有相同名称的属性functioncreatePerson(name,age){return{name,age}}对象方法的简写,sayName(){console.log(this.name)}}ES5中可计算的属性名如果属性名中包含空格或动态字符串变量作为属性名,则需要使用[]方括号来访问,如下所示varperson={},lastName='lastname';person["firstname"]='Li'person[lastName]='yunhua'适用于属性名已经或者可以预先用字符串字面量表示的情况,如果属性名"firstname"包含在一个变量中或者需要计算得到ES6支持变量值的可计算属性名}即使方括号中的内容也可以使用表达式作为属性的可计算名varsuffix='name'varperson={['first'+suffix]:'Li',['last'+suffix]:'yunhua'}也就是说括号内可以使用的任何属性名对象实例的符号也可以用作对象文字中的计算属性名称。不完全等于NaN,所以ES6参考了Object.is方法来弥补全等运算符的无准备操作。对于Object.is方法,大部分运算结果与===运算符相同,唯一的区别是+0和-0被识别为不相等,NaN和NaN被识别为相等Object.assignObject.assign方法接受任意数量的源对象并按指定顺序将属性复制到接收对象中,因此如果多个源对象具有相同名称的属性,则排名较低的源对象将覆盖排名较高的源对象。需要特别注意的一点是Object.assign方法无法将提供者的访问器属性复制到接收对象。由于Object.assign执行的是赋值操作,provider的accessor属性最终会转化为接收对象中的data属性varreceiver={},supplier={getname(){return"file.js"}}Object.assign(receiver,supplier)vardesc=Object.getOwnPropertyDescriptor(receiver,"name")console.log(desc.value)//file.jsconsole.log(desc.get)//undefinedrepeatedobjectliteralproperties在ES5严格模式下,objectliteralrepeatedproperties会报错,但是在ES6strictmode下,不会报错,取值最后'usestrict'varperson={name:'lisa',name:'angela'}console.log(person.name)//angela自身属性的枚举顺序所有的数字键都是升序排列的所有字符串都是按照添加到对象的顺序排列的所有符号键都是按照它们被添加到对象的顺序varobj={a:1,0:1,c:1,2:1,b:1,1:1}obj.d=1console.log(Object.getOwnPropertyNames(obj).join(''))//012acbd改变一个对象的原型ES5可以通过Object.getPrototypeOf返回任意指定对象的原型ES6增加了Object.setPrototypeOf来改变任意指定对象的原型varperson={getGreeting(){return'你好'}}vardog={getGreeting(){return'woof'}}letfriend=Object.create(person)console.log(friend.getGreeting())//helloconsole.log(Object.getPrototypeOf(friend)===person)//trueObject.setPrototypeOf(friend,dog)console.log(friend.getGreeting())//woofconsole.log(Object.getPrototypeOf(friend)===dog)//true简化原型如果在ES5中要调用父类的方法,如果要调用access的super引用,一般是这样实现的,即获取原型对象,然后调用Object.getPrototypeOf(this).getGreeting.call(this)varperson={getGreeting(){return'hello'}}vardog={getGreeting(){return'woof'}}varfriend={getGreeting(){returnObject.getPrototypeOf(this).getGreeting.call(this)+",hi!";}}Object.setPrototypeOf(friend,person)console.log(friend.getGreeting())//hello,hi!console.log(Object.getPrototypeOf(friend)===person)//trueObject.setPrototypeOf(friend,dog)console.log(friend.getGreeting())//woof,hi!console.log(Object.getPrototypeOf(friend)===dog)//true但是在多重继承的情况下,上面的方法是会出错,例如varperson={getGreeting(){return'hello'}}varfriend={getGreeting(){returnObject.getPrototypeOf(this).getGreeting.call(this)+",hi!";}}Object.setPrototypeOf(朋友,person)varrelative=Object.create(friend)console.log(person.getGreeting())//helloconsole.log(friend.getGreeting())//你好,嗨!console.log(relative.getGreeting())//ErrorUncaughtRangeError:MaximumcallstacksizeexceededES6可以通过super关键字轻松解决问题varperson={getGreeting(){return'hello'}}varfriend={getGreeting(){returnsuper.getGreeting.call(this)+",嗨!";}}Object.setPrototypeOf(friend,person)varrelative=Object.create(friend)console.log(person.getGreeting())//helloconsole.log(friend.getGreeting())//你好,嗨!console.log(relative.getGreeting())//你好,你可能想知道super怎么知道哪个是真正的调用对象。这其实是因为方法在ES6中被官方定义为一个函数,它内部会有一个[[HomeObject]]属性来保存这个方法从属于的对象varperson={//是方法getGreeting(){return'你好'}}functionshareGreeting(params){return'Hi!'}person.getGreeting方法的[[HomeObject]]属性是person,但是shareGreeting函数并没有将其赋值给一个对象,所以所有对其[[HomeObject]]属性super的引用都没有通过[[HomeObject]]属性明确定义以确定后续运行的进程调用[[HomeObject]]属性上的Object.getPrototypeOf方法来检索原型的引用搜索原型找到同名的函数来设置这个绑定并调用相应的方法