随着JavaScript
的发展,JavaScript
的Object
构造函数也增加了许多方法(自身方法和原型链方法。有必要全面了解一下。本文基本涵盖了下Object
所有的属性和方法介绍。如果有遗漏,还请指出。
一些未列出的属性或方法是非标准的、不推荐使用的或者已经从
Web
标准中删除的,本文将不再进行介绍。
首先需要介绍一下JavaScript
对象的属性描述符
和对象属性的可枚举性
的概念。
JS属性描述符(属性描述对象)
创建对象的方式有三种:第一种,通过new
操作符后面跟Object
构造函数,第二种,对象字面量方式。第三种,使用Object.create()
方法。如下:
const obj = {x: 5,y: 6}
const obj1 = new Object()
obj1.x = 5
obj2.x = 6
const obj2 = Object.create(Object.prototype, {
x: {
value: 5
},
y: {
value: 6
}
})
上面这三种方式创建出来的对象是一样的,有相同的属性。但是这些属性内部都有描述其行为的属性描述符
,保存该属性的一些元信息。如下图:
如果要获得对象的属性描述符
,可以通过Object.getOwnPropertyDescriptor()
来获取对象中某个属性的属性描述符
。
const obj = { x: 5, y: 6 }
const desc = Object.getOwnPropertyDescriptor(obj, 'x')
/*
{
value: 5
writable: true
enumerable: true
configurable: true
}
*/
console.log(desc)
对象里目前存在的属性描述符
有两种主要形式:数据属性描述符(data Property Descriptors )
和访问器(accessor Property Descriptors)属性描述符
。
属性描述符
特性是为了实现 JavaScript
引擎用的,因此在 JavaScript
中不能直接访问它们。为了表示特性是内部值,该规范把它们放在了两对儿方括号中,例如[[Enumerable]]
。
数据属性描述符
数据属性描述符
有4
个描述其行为的特性:
-
[[Configurable]]
: 表示能否通过delete
删除属性,能否修改属性的特性,或者能否把属性修改为访问器属性描述符
。一旦为false
,就不能再设置它的(value
,writable
,configurable
)。直接在对象上定义的属性默认值为true
。 -
[[Enumerable]]
: 表示能否能通过for-in,Object.keys(),JSON.stringify(),Object.assign()
遍历属性。默认值为true
。 -
[[Writable]]
: 表示能否修改属性的值。如果为false
,属性的值就不能被重写,只能为只读。默认值为true
。 -
[[Value]]
: 包含这个属性的值。读取属性值的时候,从这个位置读。写入属性值时,把新值保存在这个位置。默认值是undefined
。
访问器属性描述符
访问器属性有4
个描述其行为的特性:
-
[[Configurable]]
: 表示能否通过delete
删除属性,能否修改属性的特性,或者能否把属性修改为数据属性描述符
。一旦为false
,就不能再设置它的(value
,writable
,configurable
)。直接在对象上定义的属性默认值为true
。 -
[[Enumerable]]
: 表示能否能通过for-in,Object.keys(),JSON.stringify(),Object.assign()
遍历属性。默认值为true
。 -
[[Get]]
: 在读取属性时调用的函数。默认值为undefined
。 -
[[Set]]
: 在写入属性时调用的函数。默认值为undefined
。
数据属性描述符和访问器属性描述符的区别
任何属性描述符
都可以有名为[[Configurable]]
和[[Enumerable]]
的字段。数据属性描述符
含有 [[Writable]]
和 [[Value]]
特性,访问器属性描述符
含有[[Get]]
和[[Set]]
特性。
如下图所示,绿色代表该属性下可存在的特性,红色代表不可存在的特性。
[[Writable]]
、[[Value]]
和[[Get]]
、[[Set]]
之间是互斥关系。因为一个属性,它不能既属于数据属性描述符
,也属于访问器属性描述符
。如果在Object.defineProperty
中同时定义互斥特性会抛出异常。
JS属性的可枚举性
JavaScript
对象的属性可分为可枚举
和不可枚举
。它是由内部“可枚举”标志(enumerable
)决定的,true
为可枚举,false
为不可枚举。
对于通过直接的赋值和属性初始化的属性,该标识值默认为即为true
,对于通过Object.defineProperty
,Object.create
等定义的属性,该标识值默认为false
。
const obj = { x: 5 }
Object.defineProperty(obj, 'y', {
value: 6
})
const desc1 = Object.getOwnPropertyDescriptor(obj, 'x')
// {value: 5, writable: true, enumerable: true, configurable: true}
console.log(desc1)
const desc2 = Object.getOwnPropertyDescriptor(obj, 'y')
// {value: 6, writable: false, enumerable: false, configurable: false}
console.log(desc2)
可枚举的属性可以通过for...in
循环进行遍历(除非该属性名是一个 Symbol
)。
一、 Object
构造函数属性
Object.prototype
JavaScript
规定,每个函数都有一个prototype
属性,指向一个对象。所以Object
构造函数也会有一个prototype
属性。几乎所有对象都继承了Object.prototype
的属性。这就是所有对象都有valueOf
和toString
方法的原因,因为这是从Object.prototype
继承的。
Object.length
函数的 length
得到的是形参个数。所以Object.length
的形参个数是1
。
function test1(a, b, c) { }
// 3
console.log(test1.length)
function test2(a, b, c, d) { }
// 4
console.log(test2.length)
// 1
console.log(Object.length)
Object.name
Object函数的name
属性,返回该函数的函数名。
// Object
console.log(Object.name)
二、 Object
构造函数的方法
工具相关方法
Object.is()
Object.is()
方法接收两个参数,判断两个值是否是相同的值。
传入一个参数或不传参的情况。
Object.is() // true
Object.is(123) // false
Object.is(undefined) // true
Object.is(null) // false
严格相等运算符(===
)和Object.is()
的区别。
+0 === -0 // true
NaN === NaN // false
Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
绝大多数情况下,Object.is()
的结果与===
运算符是相同的。除了+0,-0
和NaN
这两种情况使用===
和Object.is()
比较返回结果不同。
Object.assign()
Object.assign
方法用于对象的合并,将源对象(source
)的所有可枚举属性
,复制到目标对象(target
)。
Array.from()
可以传入多个参数:
- 第一个参数
target
(必填):目标对象。 - 第N个参数
source
:源对象。
Object.assign(target, ...sources)
如果不传参数或者传入null
和undefined
都会抛出异常。
// Uncaught TypeError: Cannot convert undefined or null to object
Object.assign()
Object.assign(null)
Object.assign(undefined)
基本用法。
const target = { id: 1 }
const source1 = { name: 'zhangsan' }
const source2 = { age: 26 }
const newObj = Object.assign(target, source1, source2)
// {id: 1, name: "zhangsan", age: 26}defineProperty
console.log(newObj)
如果只传入一个参数,Object.assign会直接返回该参数。
const target = { id: 1, name: '刘德华' }
const newObj = Object.assign(target)
// true
console.log(newObj === target)
如果非对象参数出现在源对象的位置,这些参数都会转成对象,如果无法转成对象,就会跳过。如果undefined
和null
不在首参数,就不会报错。
const target = { id: 1, name: '刘德华' }
const newObj = Object.assign(target, 123,true)
// {id: 1, name: "刘德华"}
console.log(newObj)
const target1 = { id: 1, name: '刘德华' }
// 源对象是字符串的话会以数组形式拷贝到目标对象
const newObj1 = Object.assign(target1, '张学友')
// {0: "张", 1: "学", 2: "友", id: 1, name: "刘德华"}
console.log(newObj1)
// 其他值都不会产生效果
let target2 = { id: 1 };
Object.assign(target2, undefined) === target2 // true
Object.assign(target2, null) === target2 // true
Object.assign(target2, NaN) === target2 // true
Object.assign(target2, false) === target2 // true
Object.assign(target2, 10) === target2 // true
如果目标对象与源对象有同名属性,或多个源对象有同名属性,后面的属性就会覆盖前面的属性。
const target = { id: 1, name: '刘德华' }
const source1 = { name: '张学友', age: 50 }
const source2 = { age: 26 }
const newObj = Object.assign(target, source1, source2)
// {id: 1, name: "张学友", age: 26}
console.log(newObj)
Object.assign
拷贝的属性是有限制的,只拷贝源对象的自身属性
(不拷贝继承属性),也不拷贝不可枚举的属性
(enumerable:false
)。Object.assign
方法是浅拷贝,而不是深拷贝。如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
获取和设置对象原型的相关方法
Object.create()
Object.create()
方法会使用指定的原型对象
及属性
去创建一个新的对象。
Object.create()
可以传入2
个参数:
- 第一个参数
proto
(必填):新创建对象的原型对象,不传会抛出异常。 - 第二个参数
propertiesObject
(可选):要添加到新创建对象的属性描述符
(新添加的属性是其自身的属性,而不是其原型链上的属性)。
如果不传参数,传入undefined
或传入基本数据类型会抛出异常。
// Object prototype may only be an Object or null
Object.create(undefined)
Object.create(123)
Object.create('abc')
传入null
的情况。
const obj = Object.create(null)
console.log(obj)
传入null
的的时候,也就是将null
设置成了新创建对象的原型,这个新对象就不会有原型链了。所以新对象是非常干净的对象。
使用对象自变量和直接使用 new Object()
创建对象。
const obj = {}
console.log(obj)
const obj1 = new Object()
console.log(obj1)
从上图可以看出,使用对象自变量和直接使用new Object()
创建对象的时候,都会继承Object
构造函数的原型对象。这也是它们和使用Object.create(null)
创建出新对象的区别。
传入对象的情况。
// 自定义原型对象
const customPropertyObject = { id: 1, name: 'zhangsan' }
const obj = Object.create(customPropertyObject)
console.log(obj);
从上图可以看出 customPropertyObject
被定义在了新创建对象的原型对象上,customPropertyObject
又继承了Object
构造函数的原型对象。
也可以直接使用来指定Object.create(Object.prototype)创建出和对象自变量一样的对象。
const obj = Object.create(Object.prototype)
console.log(obj)
这和通过 const obj = {}
直接创建对象是一样的效果。
传入2
个参数。
const obj = Object.create({ id: 1 }, {
name: {
value: 'zhangsan',
enumerable: true,
configurable: true,
writable: true,
},
age: {
value: 20,
enumerable: false,
configurable: false,
writable: false,
}
})
console.log(obj)
从上图可以看到,第二个参数添加的属性是创建出的对象自身的属性。我们把age
属性设置成了不可删除
,不可枚举
,不可修改
的属性值。
obj.age = 1
delete obj.age
// id
// name
for (let prop in obj) {
console.log(prop);
}
从上图可以看出,当修改,删除obj.age
属性的时候是没有效果的,而且也没有办法通过for in
循环出来。
第二个参数传入null
会抛出异常。
// Uncaught TypeError:Cannot convert undefined or null to object
const obj = Object.create(null, null)
Object.getPrototypeOf()
Object.getPrototypeOf()
方法返回指定对象的原型,如果没有继承属性,则返回 null
。
const obj = { id: 1, name: 'zhangsan' }
// 获取的是Object的原型对象,这里省略打印...
const propertyObj = Object.getPrototypeOf(obj)
// true
console.log(propertyObj === Object.prototype)
function Car() { }
const newCar = new Car()
// true
console.log(Object.getPrototypeOf(newCar) === Car.prototype)
// Object的原型对象上没有原型对象了,就返回了null
// null
console.log(Object.getPrototypeOf(Object.prototype));
// null
console.log(Object.getPrototypeOf({}.__proto__));
使用Object.create
创建对象,并使用Object.getPrototypeOf()
获取它的原型对象。
const obj = Object.create({ id: 1 })
const propertyObj = Object.getPrototypeOf(obj)
// {id: 1}
console.log(propertyObj)
Object.setPrototypeOf()
Object.setPrototypeOf()
方法为指定对象设置原型,返回该指定对象。
Object.setPrototypeOf()
可以传入2
个参数:
- 第一个参数
obj
(必填):要设置其原型的对象。 - 第二个参数
prototype
(可选):该对象的新原型(一个对象 或null
)。
const son = { id: 1, name: 'zhangsan' }
// 要设置的原型对象
const father = { money: 100 }
const obj = Object.setPrototypeOf(son, father)
console.log(obj)
上图可以看出,Object.setPrototypeOf
方法将对象son
的原型,设置为对象father
,因此son
可以共享father
的属性。
const obj = Object.setPrototypeOf({}, null)
// 会返回一个非常干净的空 {} 对象,没有继承任何原型对象。
console.log(obj)
如果传入错误参数类型,会抛出异常。
// Uncaught TypeError: Object prototype may only be an Object or null: undefined
const obj = Object.setPrototypeOf(1)
const obj = Object.setPrototypeOf(null)
const obj = Object.setPrototypeOf(undefined)
// 第二个参数:Uncaught TypeError: Object prototype may only be an Object or null
const obj = Object.setPrototypeOf({}, undefined)
Object
操作属性描述符的相关方法
Object.defineProperty()
Object.defineProperty
方法允许通过属性描述符(数据属性描述符
和访问器属性描述符
),设置或修改一个属性,然后返回修改后的原对象。
Object.defineProperty()
可以传入3
个参数:
- 第一个参数
obj
(必填):属性所在的对象。 - 第二个参数
prop
(可选):属性名。 - 第三个参数
descriptor
(必填):属性描述符。
Object.defineProperty
设置属性的时候,如果属性不存在,则创建属性。如果属性已经存在,Object.defineProperty
方法相当于更新该属性的属性描述对象
。
如果参数错误或不填,会抛出异常。
// Uncaught TypeError: Object.defineProperty called on non-object
Object.defineProperty()
Object.defineProperty(1)
// Uncaught TypeError: Property description must be an object: undefined
Object.defineProperty({})
// Uncaught TypeError: Property description must be an object: 1
Object.defineProperty({}, 'abc', 1)
使用Object.defineProperty()
定义数据属性描述符
const obj = { id: 1 }
const newObj = Object.defineProperty(obj, 'name', {
value: 'zhangsan',
writable: false,
enumerable: true,
configurable: true
})
// true
console.log(obj === newObj)
//{id: 1, name: "zhangsan"}
console.log(obj)
newObj.id = 10
// 不可修改,严格模式下会抛出异常
newObj.name = 'lisi'
//{id: 10, name: "zhangsan"}
console.log(obj)
使用Object.defineProperty()定义访问器属性描述符
const obj = { id: 1 }
Object.defineProperty(obj, 'name', {
enumerable: true,
configurable: true,
set(newValue) {
console.log('监听对象属性修改--->我的值是:' + newValue)
},
get() {
console.log('获取对象属性');
return '刘德华' //先硬编码
}
})
// 监听对象属性修改--->我的值是:zhangsan
obj.name = 'zhangsan'
// 获取对象属性
//刘德华
console.log(obj.name)
上面这个obj.name
赋值或者取值的时候会分别触发 set 和 get 对应的函数。set
和 get
相当于监听函数。
模拟一个访问和设置的默认行为,达到我们正确的修改数据和访问数据是正确的。
const obj = { id: 1 }
// 内部 this 指向 obj
Object.defineProperty(obj, 'name', {
enumerable: true,
configurable: true,
set(newValue) {
this.name = newValue
},
get() {
return this.name
}
})
// Uncaught RangeError: Maximum call stack size exceeded
obj.name = 'zhangsan'
按照上面这么写的话会造成循环引用。obj.name = 'zhangsan'
会触发set
函数,set
函数内部 this.name = newValue
又会触发set
函数。然后无限调用....就抛出异常。需要定义一个新的属性解决问题。
const obj = { id: 1 }
// 内部 this 指向 obj
Object.defineProperty(obj, 'name', {
enumerable: true,
configurable: true,
set(newValue) {
this._name = newValue
},
get() {
return this._name || undefined
}
})
obj.name = 'zhangsan'
上面这样做法有一个缺点,就是obj
对象里多了一个_name
属性。
Object.defineProperties()
Object.defineProperties
方法允许通过属性描述符
(数据属性描述符
和访问器属性描述符
),定义或修改多个属性,然后返回修改后的原对象。
Object.defineProperties()
可以传入2
个参数:
- 第一个参数
obj
(必填):属性所在的对象。 - 第二个参数
prop
(可选):属性描述符对象。
如果参数错误或不填,会抛出异常。
// Uncaught TypeError: Object.defineProperty called on non-object
Object.defineProperties()
Object.defineProperties(1,{})
// Cannot convert undefined or null to object
Object.defineProperties({})
Object.defineProperties({},null)
const obj = { id: 1 }
Object.defineProperties(obj, {
name: { value: 'zhangsan', enumerable: true, writable: true },
age: { value: 20, enumerable: true, writable: true },
})
// {id: 1, name: "zhangsan", age: 20}
console.log(obj)
注意:
Object.defineProperty()
和Object.defineProperties()
的属性描述符对象
,它的writable
、configurable
、enumerable
这三个属性的默认值都为false
。
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor()
可以取得指定对象上一个自有属性
(非继承属性)的描述符。如果指定的属性存在于对象上,则返回其属性描述符对象
(property descriptor),否则返回 undefined
。
Object.getOwnPropertyDescriptor()
可以传入2
个参数:
- 第一个参数
obj
(必填):属性所在的对象。 - 第二个参数
prop
(可选):属性名称。
如果不传参数,会抛出异常。
// Uncaught TypeError: Cannot convert undefined or null to object
Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor(null)
Object.getOwnPropertyDescriptor(undefined)
const obj = { id: 1, name: 'zhangsan' }
Object.defineProperty(obj, 'name', {
enumerable: true,
configurable: true,
get() {
return 'get'
},
set() {
return 'set'
}
})
const descObj = Object.getOwnPropertyDescriptor(obj, 'id')
// {value: 1, writable: true, enumerable: true, configurable: true}
console.log(descObj)
// get和set是两个函数
// {enumerable: true, configurable: true, get: ƒ, set: ƒ}
const descObj1 = Object.getOwnPropertyDescriptor(obj, 'name')
console.log(descObj1);
// 因为toString是原型链上的对象,所以访问不到
// undefined
const descObj2 = Object.getOwnPropertyDescriptor(obj, 'toString')
console.log(descObj2);
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()
方法,返回指定对象所有自身属性
(非继承属性)的属性描述符对象
。如果没有任何自身属性,返回空对象。
Object.getOwnPropertyDescriptors()
可以传入1
个参数:
- 第一个参数
obj
(必填):任意对象
如果不传参数或传入错误参数,会抛出异常。
// Uncaught TypeError: Cannot convert undefined or null to object
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors(null)
Object.getOwnPropertyDescriptors(undefined)
const obj = {
id: 1,
name: 'zhangsan'
};
const descObj = Object.getOwnPropertyDescriptors(obj)
/* {
id:{
value: 1,
writable: true,
enumerable: true,
configurable: true
},
name: {
value: 1,
writable: true,
enumerable: true,
configurable: true
}
}
*/
console.log(descObj)
Object.getOwnPropertyDescriptors()
方法返回一个对象,所有原对象的属性名都是该对象的属性名,对应的属性值就是该属性的属性描述符对象
。
Object转换的相关方法
Object.keys()
Object.keys()
方法会返回由一个指定对象自身
(非继承属性)可枚举属性
组成的字符串数组。
const obj = {
id: 1,
name: 'zhangsan'
};
const props = Object.keys(obj)
// ["id", "name"]
console.log(props)
Object.keys()
可以传入1
个参数:
- 第一个参数
obj
(必填):任意对象
如果不传参数,会抛出异常。
// Uncaught TypeError: Cannot convert undefined or null to object
Object.keys()
Object.keys(null)
Object.keys(undefined)
const obj = {
id: 1,
name: 'zhangsan'
};
const props = Object.keys(obj)
// ["id", "name"]
console.log(props)
const obj1 = { 100: 'a', 2: 'b', 7: 'c' };
// ['2', '7', '100']
console.log(Object.keys(obj1));
Object.values()
Object.values()
方法返回由一个指定对象自身
(非继承属性)可枚举属性
值的数组。
Object.values()
可以传入1
个参数:
- 第一个参数
obj
(必填):任意对象
如果不传参数,会抛出异常。
// Uncaught TypeError: Cannot convert undefined or null to object
Object.values()
Object.values(null)
Object.values(undefined)
const obj = {
id: 1,
name: 'zhangsan'
}
const newObj = Object.values(obj)
// [1, "zhangsan"]
console.log(newObj)
Object.entries()
Object.entries()
方法返回由一个指定对象自身
(非继承属性)可枚举属性
的键值对数组。
Object.entries()
可以传入1
个参数:
- 第一个参数
obj
(必填):任意对象
如果不传参数,会抛出异常。
// Uncaught TypeError: Cannot convert undefined or null to object
Object.entries()
Object.entries(null)
Object.entries(undefined)
const obj = {
id: 1,
name: 'zhangsan'
}
const newObj = Object.entries(obj)
// [['id',1],['name','zhangsan']]
console.log(newObj)
for (let [key, value] of Object.entries(obj)) {
// id: 1
// name: zhangsan
console.log(`${key}: ${value}`);
}
Object.fromEntries()
Object.fromEntries()
方法是Object.entries()
的逆操作,用于将一个键值对数组转为对象。
Object.fromEntries()
可以传入1
个参数:
- 第一个参数
iterable
(必填):可迭代对象,类似Array
、Map
或者其它可迭代的对象。
如果不传参数或传入参数错误,会抛出异常。
// Uncaught TypeError: undefined is not iterable
Object.fromEntries()
Object.fromEntries(undefined)
Object.fromEntries(null)
// Uncaught TypeError: function is not iterable
Object.fromEntries(() => {})
// Uncaught TypeError: Iterator value a is not an entry object
Object.fromEntries('abc')
const map = new Map([['id', 1], ['name', 'zhangsan']])
const obj = Object.fromEntries(map)
// {id: 1, name: "zhangsan"}
console.log(obj)
const obj1 = Object.fromEntries([['id', 1], ['name', 'zhangsan']])
// {id: 1, name: "zhangsan"}
console.log(obj1)
Object.getOwnPropertyNames()
Object.getOwnPropertyNames()
方法返回一个由指定对象的所有自身属性
(非继承属性)的属性名(包括不可枚举属性
但不包括Symbol值
作为名称的属性)组成的字符串数组。
Object.getOwnPropertyNames()
可以传入1
个参数:
- 第一个参数
obj
(必填):任意对象。
如果不传参数或传入参数错误,会抛出异常。
// Uncaught TypeError: Cannot convert undefined or null to object
Object.getOwnPropertyNames()
Object.getOwnPropertyNames(undefined)
Object.getOwnPropertyNames(null)
const obj = { id: 1, name: 'zhangsan' }
const arr = Object.getOwnPropertyNames(obj)
// ["id", "name"]
console.log(arr)
Object.getOwnPropertySymbols()
Object.getOwnPropertySymbols()
方法返回一个指定对象自身的所有Symbol
属性的数组。所有的对象在初始化的时候不会包含任何的Symbol
,除非你在对象上赋值了Symbol
否则Object.getOwnPropertySymbols()
只会返回一个空的数组。
Object.getOwnPropertySymbols()
可以传入1
个参数:
- 第一个参数
obj
(必填):任意对象。
如果不传参数或传入参数错误,会抛出异常。
// Uncaught TypeError: Cannot convert undefined or null to object
Object.getOwnPropertySymbols()
Object.getOwnPropertySymbols(undefined)
Object.getOwnPropertySymbols(null)
const obj = { id: 1, name: 'zhangsan' }
obj[Symbol('age')] = 20
const arr = Object.getOwnPropertySymbols(obj)
// [Symbol(age)]
console.log(arr);
Object
对象的防篡改相关方法
Object.preventExtensions()
Object.preventExtensions()
方法让一个对象变的不可扩展,永远不能再添加新的属性。返回已经不可扩展的原对象。
Object.preventExtensions()
可以传入1
个参数:
- 第一个参数 obj :任意对象。
const obj = { id: 1, name: 'zhangsan' }
const newObj = Object.preventExtensions(obj)
// 在严格模式下,会抛出异常。
obj.age = 20
// {id: 1, name: "zhangsan"}
console.log(obj)
// true
console.log(obj === newObj)
Object.isExtensible()
Object.isExtensible()
方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。返回true
是可扩展的。
Object.isExtensible()
可以传入1
个参数:
- 第一个参数
obj
:任意对象。
const obj = { id: 1, name: 'zhangsan' }
// true
console.log(Object.isExtensible(obj))
Object.preventExtensions(obj)
// false
console.log(Object.isExtensible(obj))
Object.seal()
Object.seal()
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置([[Configurable]]
设置为false
)。当前属性的值只要封闭之前是可写的就还是可写的。返回被密封的的原对象。
Object.seal()
可以传入1
个参数:
- 第一个参数
obj
:任意对象。
const obj = { id: 1, name: 'zhangsan' }
Object.seal(obj)
// 不能新增, 严格模式下抛出异常
obj.age = 20
// 不能删除,严格模式下抛出异常
delete obj.id
Object.isSealed()
Object.isSealed()
方法判断一个对象是否被密封。返回true
是被密封的。
Object.isSealed()
可以传入1
个参数:
- 第一个参数
obj
:任意对象。
Object.freeze()
Object.freeze()
方法冻结一个对象。一个被冻结的对象再也不能被修改。冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改已有属性的值。也不能修改该对象已有属性的可枚举性、可配置性、可写性,以及。并且冻结一个对象后该对象的原型也不能被修改。freeze()
返回原对象。
Object.freeze()
可以传入1
个参数:
- 第一个参数
obj
:任意对象。
const obj = { id: 1, name: 'zhangsan',house: { 'beijing': 2 } }
Object.freeze(obj)
// 不能新增属性, 严格模式下抛出异常
obj.age = 20
// 不能删除属性,严格模式下抛出异常
delete obj.id
// 不能修改属性,严格模式下抛出异常
obj.id = 20
// 不能修改原型链,严格模式下抛出异常
obj.__proto__ = {}
// 不能修改属性描述符,严格模式下抛出异常
Object.defineProperty(obj, 'id', {
enumerable: false
})
// 如果一个属性的值是个对象,则这个对象中的属性是可以修改的,除非它也是个冻结对象。
obj.house.beijing = 3
// 3
console.log(obj.house.beijing)
被冻结对象自身的所有属性几乎都不可能以任何方式被修改。
Object.isFrozen()
Object.isFrozen()
方法判断一个对象是否被冻结。返回true
是被冻结的。
Object.isFrozen()
可以传入1
个参数:
- 第一个参数
obj
:任意对象。
const obj = { id: 1, name: 'zhangsan' }
Object.freeze(obj)
// true
console.log(Object.isFrozen(obj))
三、 Object
实例对象(Object
原型)的属性和方法
Object.prototype.constructor
prototype
对象有一个constructor
属性,默认指向prototype
对象所在的构造函数。因为Object
是一个函数,所以它的原型对象上的constructor
属性就是Function
。
// true
console.log(Object.__proto__.constructor === Function)
Object.prototype.hasOwnProperty()
对象实例的hasOwnProperty
方法返回一个布尔值,用于判断某个属性定义在对象自身,还是定义在原型链上。
Object.prototype.hasOwnProperty()
可以传入1
个参数:
- 第一个参数
obj
:要检测的属性的字符串名称,或者Symbol
。
const obj = { id: 1, name: 'zhangsan' }
// true
console.log(obj.hasOwnProperty('id'))
// false
console.log(obj.hasOwnProperty('toString'))
Object.prototype.isPrototypeOf()
对象实例的isPrototypeOf()
方法用来判断该对象是否为参数对象的原型。
Object.prototype.isPrototypeOf()
可以传入1
个参数:
- 第一个参数
obj
:在该对象的原型链上搜索
var father = { money: 100 };
var son = Object.create(father);
// true 儿子的原型是爸爸
console.log(father.isPrototypeOf(son))
//由于Object.prototype处于原型链的最顶端,所以对各种实例都返回true,只有直接继承自null的对象除外
Object.prototype.isPrototypeOf({}) // true
Object.prototype.isPrototypeOf([]) // true
Object.prototype.isPrototypeOf(/xyz/) // true
Object.prototype.isPrototypeOf(Object.create(null)) // false
Object.prototype.propertyIsEnumerable()
对象实例的propertyIsEnumerable()
方法返回一个布尔值,表示指定的属性是否可枚举。
Object.prototype.对象实例的propertyIsEnumerable()
可以传入1
个参数:
- 第一个参数
prop
:属性名
const obj = { id: 1, name: 'zhangsan' }
Object.defineProperty(obj, 'age', {
enumerable: false
})
// true
console.log(obj.propertyIsEnumerable('id'))
// false
console.log(obj.propertyIsEnumerable('age'))
// false
console.log(obj.propertyIsEnumerable('toString'))
Object.prototype.toLocaleString()
对象实例的toLocaleString()
方法返回一个该对象的字符串表示。Object toLocaleString
返回的是调用 toString()
的结果。
const obj = { id: 1, name: 'zhangsan' }
// [object Object]
console.log(obj.toLocaleString())
Object.prototype.toString()
对象实例的toString()
方法返回一个表示该对象的字符串。
toString()
检测对象类型。
var toString = Object.prototype.toString;
console.log(toString.call(new Date())) // [object Date]
console.log(toString.call({})) // [object Object]
console.log(toString.call('')) // [object String]
Object.prototype.valueOf()
对象实例的 valueOf()
方法返回指定对象的原始值。
const emptyObject = {}
// true
console.log(emptyObject.valueOf() === emptyObject)
const arr = []
// true
console.log(arr.valueOf() === arr)
参考
developer.mozilla.org/zh-CN/docs/…
es6.ruanyifeng.com/#docs/objec…