在ES5中,通过使用Lodash的_.extend(target,[sources])(或者其他选项),在ES2015中引入了Object.assign(target,[sources])。
幸运的是,对象的spread语法(ECMAScript第3阶段建议)是如何操作对象,提供了一个简短且易于遵循的语法。
在上面的例子中,...cat将cat对象复制到一个新的dog对象中。.sound属性的值woof放在最后面。
下面对可枚举属性简短的概括,以及如何区分自己与继承属性。这些是理解对象如何spread和rest语法的必要基础。
在JavaScript中,对象是键(key)和值(value)之间的关联。
key的类型通常是string或symbol。值可以是一个基本类型(string、boolean、number、undefined或null),也可以是一个object或function。
下面的对象使用了对象字面符:
属性(property)有几个属性(attribute)来描述值,还有可写的、可枚举的和可配置的状态。有关于这方面更多的细节,请参阅JavaScript中的对象属性。
可枚举属性是一个布尔值,它指的是在枚举对象属性是否可访问。
可以使用Object.keys()来枚举对象属性(有于访问自己的和可枚举的属性)。也可以使用for...in语句(枚举所有可枚举属性),等等。
name和surname是person对象可枚举的属性。
有趣的部分来了。Objectspread从源可枚举属性中克隆过来:
现在我们给person对象创建一个不可枚举的属性age。然后再看看Object的spread行为:
name和surname可枚举属从源对象person复制到clone对象中,但是不可枚举属性age并没有被复制进去。
JavaScript原型可以继承。因此对象属性可是以自己的,也可以是继承的。
接下来创建一个personB对象,并且设置它的属性为person:
Objectspread从自己的源属性中进行复制的时候,会忽略继承的属性。
对象字符符中里的Objectspread可以复制源对象自己的和可枚举的属性,并将其复制到目标对象中。
来看几个示例。下面的对象字面符实例化了一只猫:
同样的规则也适用于对象初始化的规则属性:
现在如果你交换传播对象的相对位置,结果是不同的:
Objectspread的位置和正则性质很重要。这种语法允许实现诸如对象克隆、合并和填充默认值之类的。
下面我们来看看。
使用ObjectSpread语法可以用一个简短而富有表现力的方式来克隆一个对象。下面的例子克隆了bird对象:
虽然克隆对象技术乍一看似乎很简单,但有一些细节的差异还是需要注意的。
ObjectSpread只会做一个对象的浅拷贝。只有对象本身是克隆的,而嵌套的实例不是克隆的。
laptop有一个嵌套的对象screen。如果克隆laptop对象,看看对其嵌套的对象有何影响:
然而,laptop.screen===laptopClone.screen值是true。这意味着,laptop.screen和laptopClone.screen引用相同的嵌套对象,但没有复制。
其实,你可以在任何级别上做传播。只需稍加努力,就可以克隆嵌套的对象:
doomClone是一个普通的JavaScript对象,其原型是Object.prototype,而不是Game.prototype,这是可以预期的。ObjectSpread不保存源对象的原型。
因此,调用doomClone.getMessage()会抛出一个TypeError错误,那是因为doomClone不会继承getMessage()方法。
要修复丢失的原型,需要手动使用__proto__:
不赞成使用__proto__,这里只是用来做演示。
对象传播滞后于调用构造函数创建的实例,因为它不保存原型。其意图是用来浅拷贝源对象自己和可枚举的属性。因此忽略原型的方法似乎也是合理的。
顺便说一下,使用Object.assign()可以更合理的克隆doom:
当一个对象在应用程序的多个地方共用时,直接修改这个对象可能会带来意想不到的副作用。而且跟踪这些修改也是极为蛋疼的事情。
更好的方法是使用操作不可变。不可变能更好的控制对象的修改,有利于编写纯函数。即使在一些复杂的场景中,也更容易确定对象更新的源和原因,因为数据流到一个单一的方向。
ObjectSpread方便以不可变的方式来修改对象。所设你有一个对象描述了一本书的版本信息:
不要忘记,后者会覆盖前者的规则。它给出了合并多个具有相同键对象的理由。
让我们改变一下前面的例子。现在part1和part3具有一个新的属性configuration:
newLine:在行尾添加字符串。默认为
indent:打算的行。默认值为''
multiline()函数几个示例:
使用ObjectSpread会非常简单,可以用默认值填充config对象。在对象字面符中首先展开默认对象,然后是config对象:
...defaultConfig从默认值中提取属性,然后...config配置将会覆盖以前的默认值和自定义属性值。
因此,safeConfig具有multiline()函数可以使用的全部属性。无论输入的配置是否会遗漏一些属性,safeConfig都会具备必要的值。
ObjectSpread能非常直观的使用默认值。
ObjectSpread非常酷的地方在于可以在嵌套对象上使用。当更新一个大对象时,这是一个很好的优势,具有很好的可读性。但还是推荐使用Object.assign()来替代。
下面的box对象定义了box的标签:
通过增加box.size.height使box变高。只需要在嵌套对象上扩展height属性:
...box可以确保biggerBox接收来自box源的属性。
更新嵌套对象box.size的height,只需要额外的一个对象字面量{...box.size,height:200}。这样一来,box.size的height属性就得到了一个新值,其值更新为200。
我喜欢通过一个语句执行多个更新的可能性。
如何将颜色改为黑色,将宽度增加到400,并添加一个新的项目ruler到items中(使用扩展数组)?这很简单:
当扩展undefined、null或原始值时,不会提取任何属性,也不会抛出任何错误。中会返回一个空的对象:
使用结构赋值将对象的属性提取到变量之后,剩余的属性可以被收集到rest对象中。
这就是对象rest属性的好处:
Objectrest只收集自己的和可枚举的属性。
注意,Objectrest必须是结构性赋值中的最后一个元素。因此const{...margin,width}=style将会报错:SyntaxError:Restelementmustbelastelement。
Objectspread有一些规则要记住:
它从源对象中提取自己的和可枚举的属性
扩展的属性具有相同键的,后者会覆盖前者
与此同时,Objectspread是简短而且富有表现力的,同时在嵌套对象上也能很好的工作,同时也保持更新的不变性。它可以轻松的实现对象克隆、合并和填充默认属性。
在结构性赋值中使用Objectrest语法,可以收集剩余的属性。
实际上,Objectrest和Objectspread是JavaScript的重要补充。
java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!