(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!)
(注2:更多内容请查看我的目录。)
1. 简介
Object是ECMAScript中使用最多的一个类型,所有引用类型默认都继承Object,这种既成通过原型链实现,所有对象从Object.prototype继承方法和属性,尽管它们可能被覆盖。
例如,其他构造函数的原型将覆盖constructor属性并提供自己的toString()方法。Object原型对象的更改将传播到所有对象,除非受到这些更改的属性和方法将沿原型链进一步覆盖。
所以我们需要对Object的内置属性和方法有一个清晰的认识。
2. Object构造函数的使用
前面我们讲过创建对象的各种方法。其中,Object构造函数为给定值创建一个对象包装器。
如果给定值是null或undefined,将会创建并返回一个空对象。否则,将返回一个与给定值对应类型的对象。
当以非构造函数形式被调用时,Object 等同于 new Object()。
3. Object构造函数的属性与方法
我们用Object.getOwnPropertyNames()方法获取Object构造函数的所有属性与方法。
Object.getOwnPropertyNames(Object);
// (23) ["length", "name", "prototype", "assign", "getOwnPropertyDescriptor", "getOwnPropertyDescriptors", "getOwnPropertyNames", "getOwnPropertySymbols", "is", "preventExtensions", "seal", "create", "defineProperties", "defineProperty", "freeze", "getPrototypeOf", "setPrototypeOf", "isExtensible", "isFrozen", "isSealed", "keys", "entries", "values"]
发现一共有23个属性和方法。
3.1 Object构造函数的属性
Object.length
长度为1
Object.name
名称为"Object"
Object.prototype
指向Object构造函数的原型,可以为所有 Object 类型的对象添加属性。
3.2 Object构造函数的方法
Object.assign()
用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,复制过程对已存在的属性会进行覆盖。它将返回目标对象。
var obj = {
a: 0,
d: 6
}
var obj1 = {
a: 1,
b: 2
}
Object.defineProperty(obj1, 'c', {
value: 3,
enumerable: false
});
var obj2 = Object.assign(obj, obj1);
console.log(obj); // {a: 1, d: 6, b: 2}
console.log(obj2); // {a: 1, d: 6, b: 2}
Object.create()
使用指定的原型对象及其属性去创建一个新的对象。(具体可参考JS入门难点解析10-创建对象)
Object.defineProperty()
直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。(具体可参考JS入门难点解析13-属性描述符,数据属性和访问器属性)
Object.defineProperties()
直接在一个对象上定义多个新属性,或者修改一个对象的现有属性,并返回这个对象。
Object.entries()
该方法接收一个对象为参数,返回该对象自身可枚举属性的键值对数组,其排列与使用for...in...循环循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。(具体可参考JS常用方法整理-遍历对象)
Object.freeze()
可以冻结一个对象,冻结指的是不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,以及不能修改该对象已有属性的可枚举性、可配置性、可写性。也就是说,这个对象永远是不可变的。该方法返回被冻结的对象。(具体可参考JS入门难点解析13-属性描述符,数据属性和访问器属性)
Object.getOwnPropertyDescriptor()
返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
Object.getOwnPropertyNames()
返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。(具体可参考JS常用方法整理-遍历对象)
Object.getOwnPropertySymbols()
回一个给定对象自身的所有 Symbol 属性的数组。
Object.getPrototypeOf()
返回指定对象的原型(内部[[Prototype]]属性的值)。
Object.is()
判断两个值是否是相同的值。如果下列任何一项成立,则两个值相同:
- 两个值都是 undefined
- 两个值都是 null
- 两个值都是 true 或者都是 false
- 两个值是由相同个数的字符按照相同的顺序组成的字符串
- 两个值指向同一个对象
- 两个值都是数字并且
- 都是正零 +0
- 都是负零 -0
- 都是 NaN
- 都是除零和NaN外的其它同一个数字
这种相等性判断逻辑和传统的 == 运算符所用的不同,== 运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 "" == false 为 true 的现象),但 Object.is 不会做这种类型转换。
这与 === 运算符也不一样。=== 运算符(和 == 运算符)将数字值-0和+0视为相等,并认为Number.NaN不等于NaN
Object.is('foo', 'foo'); // true
Object.is(window, window); // true
Object.is('foo', 'bar'); // false
Object.is([], []); // false
var test = { a: 1 };
Object.is(test, test); // true
Object.is(null, null); // true
// 特例
Object.is(0, -0); // false
Object.is(-0, -0); // true
Object.is(NaN, 0/0); // true
Object.isExtensible()
判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。
Object.isFrozen()
判断一个对象是否是被冻结的。
Object.isSealed()
判断一个对象是否是被密封的。
Object.keys()
返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用for...in...循环遍历该对象时返回的顺序一致 (两者的主要区别是for-in 循环还会枚举其原型链上的属性)。
Object.preventExtensions()
让一个对象变的不可扩展,也就是永远不能再添加新的属性。
Object.seal()
让一个对象密封,并返回被密封后的对象。密封对象将会阻止向对象添加新的属性,并且会将所有已有属性的可配置性(configurable)置为不可配置(false),即不可修改属性的描述或删除属性。但是可写性描述(writable)为可写(true)的属性的值仍然可以被修改。
Object.setPrototypeOf()
设置一个指定的对象的原型 ( 即, 内部[[Prototype]]属性)到另一个对象或null
注意:Object.setPrototypeOf()是ECMAScript 6最新草案中的方法,相对于Object.prototype._proto_,它被认为是修改对象原型更合适的方法。但是,如果你关心性能,你应该避免设置一个对象的[[Prototype]]。相反,你应该使用 Object.create()来创建带有你想要的[[Prototype]]的新对象。
Object.values()
返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用for-in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
4. Object原型对象的属性与方法
我们用Object.getOwnPropertyNames()方法获取Object原型对象的所有属性与方法。
Object.getOwnPropertyNames(Object.prototype);
// (12) ["constructor", "__defineGetter__", "__defineSetter__", "hasOwnProperty", "__lookupGetter__", "__lookupSetter__", "isPrototypeOf", "propertyIsEnumerable", "toString", "valueOf", "__proto__", "toLocaleString"]
发现一共有12个属性和方法。
4.1 Object原型对象的属性
Object.prototype.constructor
指向构造函数Object
Object.prototype._proto_
对于Object.prototype,其值为null,以此避免无限循环。构造函数新建实例对象时,在实例对象调用会指向实例对象的原型对象。该特性为非标准特性,尽量不要使用。
4.2 Object原型对象的方法
Object.prototype.hasOwnProperty()
该方法会返回一个布尔值,指示对象自身属性(非原型链继承)中是否具有指定的属性。
Object.prototype.isPrototypeOf()
该方法返回一个布尔值,表示指定的对象是否在本对象的原型链中。
Object.prototype.PropertyIsEnumerable()
该方法返回一个布尔值,判断指定属性是否可枚举。
Object.prototype.toString()
如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中type是对象的类型。对于Object.prototype.toString(),其值为"[object Object]"。
Object.prototype.toLocalString()
返回一个该对象的字符串表示。此方法被用于派生对象为了特定语言环境的目的(locale-specific purposes)而重载使用。绝大多数情况下和Object.prototype.toString()一样。
Object.prototype.valueOf()
返回值为该对象的原始值。
5. Object实例对象的属性与方法
我们用Object.getOwnPropertyNames()方法获取Object实例对象的所有属性与方法。
var obj = new Object({a:1,b:2});
Object.getOwnPropertyNames(obj); // ["a", "b"]
传入属性的key值即为其属性。但是有一点要注意的是,此时可以使用obj._proto指向其原型对象,这个_proto属性按照《JAvaScript高级程序设计》一书和我们前面的分析,按道理应该是实例属性,但这里却并不是(或者是虽然是,但是无法被Object.getOwnPropertyNames()方法列出,如果这样的话,也说得通),不知道底层具体是如何来实现的,如果是共享自Object原型,为什么每一个实例的值都是不同的。(如果有懂这块的同学,还请不吝赐教。)