ES6 对象的新功能与解构赋值介绍


Posted in Javascript onFebruary 05, 2019

ES6 通过字面量语法扩展、新增方法、改进原型等多种方式加强对象的使用,并通过解构简化对象的数据提取过程。

一、字面量语法扩展

在 ES6 模式下使用字面量创建对象更加简洁,对于对象属性来说,属性初始值可以简写,并可以使用可计算的属性名称。对象方法的定义消除了冒号和 function 关键字,示例如下:

// Demo1
var value = "name", age = 18
var person = {
 age, // age: age
 ['my' + value]: 'Jenny', // myname
 sayName () { // sayName: function()
  console.log(this.myname)
 }
}
console.log(person.age) // 18
console.log(person.myname) // Jenny
person.sayName(); // Jenny

针对重复定义的对象字面量属性,ES5严格模式下会进行重复属性检查从而抛出错误,而ES6移除了这个机制,无论严格模式还是非严格模式,同名属性都会取最后一个值。

// demo2
var person = {
 ['my' + value]: 'Jenny',
 myname: 'Tom',
 myname: 'Lee',
}
console.log(person.myname) // Lee

二、新增方法

从 ES5 开始遵循的一个设计目标是,避免创建新的全局函数,也不在object.prototype上创建新的方法。

为了是某些任务更容易实现,ES6 在全局 Object 对象上引入一些新的方法。

2.1 Object.is( )

ES6 引入Object.is()方法来弥补全等运算符的不准确计算。

全等运算符在比较时不会触发强制转换类型,Object.is()运行结果也类似,但对于 +0 和 -0(在 JS 引擎中为两个不同实体)以及特殊值NaN的比较结果不同,示例来看:

// demo3
console.log(5 == '5') // true
console.log(5 === '5') // false
console.log(Object.is(5, '5')) // false

console.log(+0 == -0) // true
console.log(+0 === -0) // true
console.log(Object.is(+0, -0)) // false

console.log(NaN == NaN) // false
console.log(NaN === NaN) // false
console.log(Object.is(NaN, NaN)) // true

总结来说,Object.is()对所有值进行了更严格等价判断。当然,是否使用Object.is()代替全等操作符(===)取决于这些特殊情况是否影响代码。

2.2 Object.assign( )

ES6 添加Object.assign()来实现混合(Mixin)模式,即一个对象接收另一个对象的属性和方法。注意是接收而不是继承,例如接收 demo1 中的对象:

// demo4
var friend = {}
Object.assign(friend, person)
friend.sayName() // Jenny
console.log(friend.age) // 18
console.log(Object.getPrototypeOf(friend) === person) // false

在Object.assign()之前,许多 JS 库自定义了混合方法 mixin( ) 来实现对象组合,代码类似于:

function mixin(receiver, supplier) {
 Object.keys(supplier).forEach(function (key) {
  receiver[key] = supplier[key]
 })
 return receiver
}

可以看出 mixin( ) 方法使用“=”赋值操作,并不能复制访问器属性,同理Object.assign()也不能复制访问器属性,只是执行了赋值操作,访问器属性最终会转变为接收对象的数据属性。示例如下:

// demo5
var animal = {
 name: 'lili',
 get type () {
  return this.name + type
 },
 set type (news) {
  type = news
 }
}
animal.type = 'cat'
console.log(animal.type) // lilicat

var pet = {}
Object.assign(pet, animal)
console.log(animal) // { name: 'lili', type: [Getter/Setter] }
console.log(pet) // { name: 'lili', type: 'lilicat' }

2.3 Object.setPrototypeOf( )

正常情况下对通过构造函数或Object.create()创建时,原型是被指定的。ES6 添加Object.setPrototypeOf() 方法来改变对象的原型。

例如创建一个继承 person 对象的 coder 对象,然后改变 coder 对象的原型:

// demo6
let person = {
 myname: 'Jenny',
 sayName () { 
  console.log(this.myname)
 }
}

// 创建原型为 person 的 coder 对象
let coder = Object.create(person) 
coder.sayName() // Jenny
console.log(Object.getPrototypeOf(coder) === person) // true

let hero = {
 myname: 'lee',
 sayName () {
  console.log(this.myname)
 }
}

// 改变 coder 对象的原型为 hero
Object.setPrototypeOf(coder, hero)
coder.sayName() // lee
console.log(Object.getPrototypeOf(coder) === hero) // true

对象原型被存储在内部专有属性[[Prototype]],调用Object.getPrototypeOf()返回存储在其中的值,调用Object.setPrototypeOf()改变其值。这个方法加强了对对象原型的操作,下一节重点讲解其它操作原型的方式。

三、增强对象原型

原型是 JS 继承的基础,ES6 针对原型做了很多改进,目的是更灵活地方式使用原型。除了新增的Object.setPrototypeOf()改变原型外,还引入Super关键字简化对原型的访问,

3.1 Super关键字

ES6 引入Super来更便捷的访问对象原型,上一节介绍 ES5 可以使用Object.getPrototypeOf()返回对象原型。举例说明Super的便捷,当对象需要复用原型方法,重新定义自己的方法时,两种实现方式如下:

// demo7
let coder1 = {
 getName () {
  console.log("coder1 name: ")
  Object.getPrototypeOf(this).sayName.call(this)
 }
}

// 设置 coder1 对象的原型为 hero(demo6)
Object.setPrototypeOf(coder1, hero)
coder1.getName() // coder1 name: lee

let coder2 = {
 getName () {
  console.log("coder2 name: ")
  super.sayName()
 }
}

Object.setPrototypeOf(coder2, hero)
coder2.getName() // coder2 name: lee

在 coder1 对象的 getName 方法还需要call(this)保证使用的是原型方法的 this,比较复杂,并且在多重继承会出现递归调用栈溢出错误,而直接使用Super就很简单安全。

注意必须在简写方法中使用Super,要不然会报错,例如以下代码运行语法错误:

let coder4= {
 getName: function () { // getName () 正确
  super.sayName() // SyntaxError: 'super' keyword unexpected here
 }

因为在例子中 getName 成为了匿名 function 定义的属性,在当前上下问调用Super引用是非法的。如果不理解,可以进一步看下方法的从属对象。

3.2 方法的从属对象

ES6 之前“方法”是具有功能而非数据的对象属性,ES6 正式将方法定义为有 [[HomeObject]]内部属性的函数。

[[HomeObject]]属性存储当前方法的从属对象,例如:

let coder5 = {
 sayName () {
  console.log("I have HomeObject")
 }
}

function shareName () {
  console.log("No HomeObject")
}

coder5 对象的 sayName( ) 方法的[[HomeObject]]属性值为 coder5,而 function 定义的 shareName( ) 没有将其赋值给对象,所以没有定义其[[HomeObject]]属性,这在使用Super时很重要。

Super就是在[[HomeObject]]属性上调用Object.getPrototypeOf()获得原型的引用,然后搜索原型得到同名函数,最后设置 this 绑定调用相应方法。

四、解构赋值

ES6 为数组和对象字面量提供了新特性——解构,可以简化数据提取的过程,减少同质化的代码。解构的基本语法示例如下:

let user = {
 name: 'jenny',
 id: 18
}
let {name, id} = user
console.log(name, id) // jenny 18

注意在这段代码中,user.name 存储在与对象属性名同名的 name 变量中。

4.1 默认值

如果解构时变量名称与对象属性名不同,即在对象中不存在,那么这个变量会默认为undefined:

let user = {
 name: 'jenny',
 id: 18
}
let {name, id, job} = user
console.log(name, id, job) // jenny 18 undefined

4.2 非同名变量赋值

非同名变量的默认值为undefined,但更多时候是需要为其赋值的,并且会将对象属性值赋值给非同名变量。ES6 为此提供了扩展语法,与对象字面量属性初始化程序很像:

let user = {
 name: 'jenny',
 id: 18
}
let {name, id = 16, job = 'engineer'} = user
console.log(name, id, job) // jenny 18 engineer

let {name: localName, id: localId} = user
console.log(localName, localId) // jenny 18

let {name: otherName = 'lee', job: otherJob = 'teacher'} = user
console.log(otherName, otherJob) // jenny teacher

可以看出这种语法实际与对象字面量相反,赋值名在冒号左,变量名在右,并且解构赋值时,只是更新了默认值,不能覆盖对象原有的属性值。

4.3 嵌套解构

解构嵌套对象的语法仍然类似对象字面量,使用花括号继续查找下层结构:

let user = {
 name: 'jenny',
 id: 18,
 desc: {
  pos: {
   lng: 111,
   lat: 333
  }
 }
}

let {desc: {pos}} = user
console.log(pos) // { lng: 111, lat: 333 }

let {desc: {pos: {lng}}} = user
console.log(lng) // 111

let {desc: {pos: {lng: longitude}}} = user
console.log(longitude) // 111

五、对象类别

ES6 规范定义了对象的类别,特别是针对浏览器这样的执行环境。

  • 普通(Ordinary)对象

具有 JS 对象所有的默认内部行为

  • 特异(Exotic)对象

具有某些与默认行为不符的内部行为

  • 标准(Standard)对象

ES6 规范中定义的对象
可以是普通对象或特异对象,例如 Date、Array 等

  • 内建对象

脚本开始执行时存在于 JS 执行环境中的对象
所有标准对象都是内建对象

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
被jQuery折腾得半死,揭秘为何jQuery为何在IE/Firefox下均无法使用
Jan 22 Javascript
了解jQuery技巧来提高你的代码(个人觉得那个jquery的手册很不错)
Feb 10 Javascript
JS保留小数点(四舍五入、四舍六入)实现思路及实例
Apr 25 Javascript
正则表达式中特殊符号及正则表达式的几种方法总结(replace,test,search)
Nov 26 Javascript
原生javascript实现Tab选项卡切换功能
Jan 12 Javascript
js实现正则匹配中文标点符号的方法
Dec 23 Javascript
Javascript实现图片轮播效果(一)让图片跳动起来
Feb 17 Javascript
JS产生随机数的几个用法详解
Jun 22 Javascript
JS匿名函数实例分析
Nov 26 Javascript
angular2 ng2 @input和@output理解及示例
Oct 10 Javascript
微信小程序http连接访问解决方案的示例
Nov 05 Javascript
vue-model实现简易计算器
Aug 17 Javascript
Vue从TodoList中学父子组件通信
Feb 05 #Javascript
详解webpack编译速度提升之DllPlugin
Feb 05 #Javascript
基于Webpack4和React hooks搭建项目的方法
Feb 05 #Javascript
利用Dectorator分模块存储Vuex状态的实现
Feb 05 #Javascript
小程序页面动态配置实现方法
Feb 05 #Javascript
PHP实现基于Redis的MessageQueue队列封装操作示例
Feb 02 #Javascript
AngularJS实现的自定义过滤器简单示例
Feb 02 #Javascript
You might like
php的ajax简单实例
2014/02/27 PHP
PHP数据的提交与过滤基本操作实例详解
2016/11/11 PHP
简单实用的PHP文本缓存类实例
2019/03/22 PHP
TP5框架简单登录功能实现方法示例
2019/10/31 PHP
Javascript的构造函数和constructor属性
2010/01/09 Javascript
qTip 基于JQuery的Tooltip插件[兼容性好]
2010/09/01 Javascript
jQuery简单实现QQ空间点赞已经取消点赞
2015/04/02 Javascript
Javascript常用小技巧汇总
2015/06/24 Javascript
实现高性能JavaScript之执行与加载
2016/01/30 Javascript
JavaScript中匿名函数的用法及优缺点详解
2016/06/01 Javascript
jQuery实现的购物车物品数量加减功能代码
2016/11/16 Javascript
JavaScript学习总结之正则的元字符和一些简单的应用
2017/06/30 Javascript
详解使用vue实现tab 切换操作
2017/07/03 Javascript
微信小程序movable view移动图片和双指缩放实例代码
2017/08/08 Javascript
微信小程序性能优化之checkSession的使用
2019/03/06 Javascript
uni-app微信小程序登录并使用vuex存储登录状态的思路详解
2019/11/04 Javascript
linux系统使用python监控apache服务器进程脚本分享
2014/01/15 Python
python去掉空白行的多种实现代码
2018/03/19 Python
python 读取DICOM头文件的实例
2018/05/07 Python
selenium+python自动化测试之多窗口切换
2019/01/23 Python
Django重置migrations文件的方法步骤
2019/05/01 Python
Python从入门到精通之环境搭建教程图解
2019/09/26 Python
超实用的 30 段 Python 案例
2019/10/10 Python
Tensorflow实现将标签变为one-hot形式
2020/05/22 Python
如何用python写个模板引擎
2021/01/14 Python
用canvas画心电图的示例代码
2018/09/10 HTML / CSS
HTML5 实现图片上传预处理功能
2020/02/06 HTML / CSS
最新党员的自我评价分享
2013/11/04 职场文书
党校培训思想汇报
2013/12/30 职场文书
给面试官的感谢信
2014/02/01 职场文书
体育教师个人的自我评价
2014/02/16 职场文书
数学兴趣小组活动总结
2014/07/08 职场文书
三严三实学习心得体会
2014/10/13 职场文书
亮剑观后感300字
2015/06/05 职场文书
2016年第32个教师节致辞
2015/11/26 职场文书
Python内置的数据类型及使用方法
2022/04/13 Python