【ES6】对象的新功能与解构赋值
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
<p>可以看出这种语法实际与对象字面量相反,<strong>赋值名在冒号左,变量名在右</strong>,并且解构赋值时,只是更新了默认值,不能覆盖对象原有的属性值。</p>
<h2>4.3 嵌套解构</h2>
<p>解构嵌套对象的语法仍然类似对象字面量,使用<strong>花括号</strong>继续查找下层结构:</p>
<pre><code class="Javascript">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 执行环境中的对象
所有标准对象都是内建对象
推荐阅读《深入理解ES6》
加油哦,少年~
来源:https://segmentfault.com/a/1190000016746873
【ES6】对象的新功能与解构赋值的更多相关文章
- ES6学习随笔--字符串模板、解构赋值、对象、循环、函数、Promise、Generrator
在线编译器:babel.github 在nongjs中使用 'use strict' let a = ; 运行node : node --harmony_destructuring xxx.js 代码 ...
- ES6学习笔记之变量的解构赋值
变量的解构赋值 ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 数组的解构赋值 以前,为变量赋值,只能直接指定值: 1 2 3 var a = 1; var b = 2; ...
- ES 6 系列 - 赋值的新方式:解构赋值
变量的解构赋值 es 6 允许按照一定的模式,从数组和对象中提取值,然后对变量进行赋值,这被称之为解构: 一.数组的解构赋值 最基本写法: let [a, b, c] = [1, 2, 3]; a / ...
- ES6学习----let、const、解构赋值、新增字符串、模板字符串、Symbol类型、Proxy、Set
这篇es6的学习笔记来自于表哥 表严肃,是我遇到过的讲课最通透,英文发音最好听的老师,想一起听课就去这里吧 https://biaoyansu.com/i/hzhj1206 ES6就是JS6,JS的第 ...
- ES6 - 基础学习(3): 变量的解构赋值
解构赋值概述 1.解构赋值是对赋值运算符的扩展. 2.它是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值. 3.代码书写上显得简洁且易读,语义更加清晰明了:而且还方便获取复杂对象中的数据字 ...
- ES6学习 第二章 变量的解构赋值
前言 该篇笔记是第二篇 变量的解构赋值. 这一章原文链接: 变量的解构赋值 解构赋值 ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 解构 ...
- ES6(二) Destructuring-变量的解构赋值
1.解构的含义 允许按照一定的模式,从数组和对象中取值,对变量进行赋值,称为解构. 解构赋值时,只要等号右边的值不是对象,就先将其转换成对象. 本质上,这种写法属于 “模式匹配”,只要两边模式相同,左 ...
- ES6标准入门之变量的解构赋值简单解说
首先我们来看一看解构的概念,在ES6标准下,允许按照一定模式从数组和对象中提取值,然后对变量进行赋值,这被称作解构,简而言之粗糙的理解就是变相赋值. 解构赋值的规则是,只要等号右边的值不是对象或者数组 ...
- ES6系列_3之变量的解构赋值
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构. 解构有三种类型: 1.数组的解构赋值 (1)简单的数组解构 以前,我们给变量赋值是直接单个指定值,比如: let a=0; ...
随机推荐
- MySQL错误日志显示(Got an error reading communication packets)的问题
错误显示: 2019-05-28T12:54:08.267934+08:00 820396 [Note] Aborted connection 820396 to db: 'Databaseplatf ...
- vue的transition的name作用
记录一下今天在vue的transition中遇到的坑 <!DOCTYPE html> <html> <head> <title>Vue中CSS动画原理& ...
- Composite UI Application Block(CAB)
序言 资料 https://www.cnblogs.com/lglruirui/archive/2010/06/21/1761737.html?tdsourcetag=s_pcqq_aiomsg ht ...
- BZOJ 2217: [Poi2011]Lollipop 构造 + 思维
Description 有一个长度为n的序列a1,a2,...,an.其中ai要么是1("W"),要么是2("T").现在有m个询问,每个询问是询问有没有一个连 ...
- JMS学习六(ActiveMQ消息传送模型)
ActiveMQ 支持两种截然不同的消息传送模型:PTP(即点对点模型)和Pub/Sub(即发布 /订阅模型),分别称作:PTP Domain 和Pub/Sub Domain. 一.PTP消息传送模型 ...
- 第四周总结 & 实验报告(二)
第四周课程总结 一.String类 1.实例化 (1)直接赋值 public class Xxxx{ public static void main(String args[]){ String a ...
- hashMap与 hashTable , ArrayList与linkedList 的区别(详细)
ArrayList 采用的是数组形式来保存对象的,这种方式将对象放在连续的位置中,所以最大的缺点就是插入删除时非常麻烦LinkedList 采用的将对象存放在独立的空间中,而且在每个空间中还保存下一个 ...
- 阶段2 JavaWeb+黑马旅游网_15-Maven基础_第3节 maven标准目录结构和常用命令_07maven常用命令
以给的hellowordl的的代码为例. src/main/java下,这是主业务逻辑代码 里面的内容只有一个jsp的跳转 测试包下: 里面很简单的就输出了一句话 复制项目的目录 先cd进入复制的这个 ...
- 深入理解java:1. JVM虚拟机的构成
1.JVM虚拟机的构成 什么是Java虚拟机? 作为一个Java程序员,我们每天都在写Java代码,我们写的代码都是在一个叫做Java虚拟机的东西上执行的. 但是如果要问什么是虚拟机,恐怕很多人就会模 ...
- Canvas入门08-绘制仪表盘
需求 实现下图所示的仪表盘的绘制. 分析 我们先来将仪表盘进行图形拆分,并定义尺寸. 我们绘制的逻辑: 绘制中心圆 绘制环外圈圆 绘制环内圈圆 绘制刻度内圈圆 绘制刻度线 绘制刻度文字 绘制指针 定义 ...