引用类型之 Object(一)
本系列的主要内容是讲解 Object 和 Function 类型,其中还包括了 Array 、Map、Set 等类型。
今天第一讲,我们就来说说这个我们最熟悉也最好用的 —— Object。
Object 构造函数
文档原文:
The Object constructor is the %Object% intrinsic object and the initial value of the Object property of the global object. When called as a constructor it creates a new ordinary object. When Object is called as a function rather than as a constructor, it performs a type conversion.
The Object constructor is designed to be subclassable. It may be used as the value of an extends clause of a class definition.
翻译后如下:
Object 构造函数是 %Object% 内在对象和全局对象的 Object 属性的初始值。当被称为构造函数时,它创建一个新的普通对象。 当 Object 作为函数而不是作为构造函数调用时,它执行类型转换。
Object 构造函数设计为可子类化。它可以用作类定义的 extends 子句的值。
Object 构造函数的属性
和其他的方法一样,构造函数的属性都由 Function.prototype 继承而来。接下来我们一一介绍 Object 的构造函数的方法吧。
(1)Object.assign (* target, ...sources* )
概述: 该函数用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。
注意:必须是可枚举的对象;其次,这是浅复制,只是将引用地址复制过来,而不是在内存中新创建一个存储空间(即,是对象的�属性的引用而不是对象本身的引用)。
示例如下:
let obj = { a: 'Hello' };
let obj1 = { b: 'World' };
console.log( Object.assign(obj1,obj) );
console.log( obj );
输出结果如下图:

我们可以看出来,复制的仅仅是* obj* 对象的属性,而不是将其对象复制过来。最后的输出的结果原对象属性未发生改变足以证明该论点。
接下来我们证明该方法只能复制可枚举的属性这一观点:
代码形式:

输出结果:

这也能说明问题了吧。
那我们来看看内部解释过程是如何的吧:
将 sources 参数作为 List 进行存储;如果传入 undefined 或 null,则返回空的 List;否则,在内部调用 [[GetOwnProperty]] 方法;如果传入的值不为 undefined 或 [[Enumerable]] 为 true,则获取并复制它到目标对象中。
这里我发现了一个有趣的现象,就是:调用该函数后对象属性的默认排列是按照字母表 [a-z] 的顺序进行排列的。
比如 name
复制到目标对象后会排在 list
后面,因为字母表中 n
在 l
的后面。
需要注意的是,这是 **ES6 **中新添加的方法。
(2)Object.create ( O, Properties )
概述:该方法创建一个拥有指定原型和若干个指定属性的对象。
代码表示如下:

我们来看下输出结果:

我们可以看出来,我们使用该方法后,obj2
原型链上拥有 obj1
的属性和 obj
的属性;obj1
上拥有 obj
的属性,就这样层层继承下来;而 true 也显示出 obj
确实是 obj1
对象的原型。
这个方法可能需要好好理解一下,主要是关于原型继承的知识点不容易在脑海中形成一条清晰的线。
(3)Object.defineProperties ( O, Properties )
概述:defineProperties 函数用于添加自己的属性 和/或 更新对象的现有自有属性的属性。
而 Object.defineProperty() 函数也是一个意思,所以就不再介绍了。主要的区别:添加一个属性还是添加多个属性。
代码表示:

输出结果:

也可以更改其中的 "a" 或 "b" 的属性值。
(4)Object.freeze ( O )
概述:该方法可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。
这个方法在内部解释时调用的是 SetIntegrityLevel(O, "frozen")
方法。
这个方法大家记住它的定义,以及和 Object.seal()
和 Object.preventExtensions()
方法的区别和联系。
(5)Object.seal ( O )
概述:该方法可以让一个对象密封,并返回被密封后的对象。密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性、可配置性、可写性,但可能可以修改已有属性的值的对象。
这个方法在内部解释时调用的是 SetIntegrityLevel(O, "sealed")
方法。
(6)Object.preventExtensions ( *O *)
概述:该方法使一个对象变的不可扩展,也就是永远不能再添加新的属性。
这个方法在内部解释时调用的是 [[PreventExtensions]]()
方法。
至此,三个方法我们都一起学习了,那么它们的区别在哪里呢?区别在于:
- Object.freeze() 方法使对象什么都不能做,已经被完全冻结了。
- Object.seal() 方法使对象只可修改属性的值,而别的都不能做。
- Object.preventExtensions() 方法使对象不可以再添加新属性,但对原属性是可以进行修改的。
希望大家将它们的区别都牢牢记住,在使用的时候才不会出错。
总结
第一节我们就到这里,我们学习了这些方法都是我们可能会经常用到的。需要大家好好认真地反复阅读和理解。