前言
在 JavaScript 中,幾乎所有的對(duì)象都是 Object
類型的實(shí)例签赃,它們都會(huì)從 Object.prototype
繼承屬性和方法,雖然大部分屬性都會(huì)被覆蓋(shadowed)或者說(shuō)被重寫了(overridden)。 除此之外绢馍,Object
還可以被故意的創(chuàng)建,但是這個(gè)對(duì)象并不是一個(gè)“真正的對(duì)象”(例如:通過(guò) Object.create(null)
)肠套,或者通過(guò)一些手段改變對(duì)象舰涌,使其不再是一個(gè)“真正的對(duì)象”(比如說(shuō):Object.setPrototypeOf
)。
靜態(tài)方法
Object.create
創(chuàng)建一個(gè)新對(duì)象你稚,使用現(xiàn)有的對(duì)象來(lái)作為新創(chuàng)建對(duì)象的原型(prototype)瓷耙。
let obj = Object.create(null)
let o1 = {
name: 'abc',
say() {
console.log(this.name)
}
}
let o2 = Object.create(o1)
o2.name = 'ABC'
o2.say() // ABC
Object.getPrototypeOf()
返回指定對(duì)象的原型(內(nèi)部[[Prototype]]
屬性的值)朱躺。
function Foo() {}
let foo = new Foo()
Object.getPrototypeOf(foo) === Foo.prototype // true
Object.setPrototypeOf()
設(shè)置一個(gè)指定的對(duì)象的原型(即,內(nèi)部 [[Prototype]]
屬性)到另一個(gè)對(duì)象或null
const obj = {}
Object.setPrototypeOf(obj, null)
Object.getOwnPropertyDescriptors()
獲取一個(gè)對(duì)象的所有自身屬性的描述符哺徊。(自有屬性指的是直接賦予該對(duì)象的屬性室琢,不需要從原型鏈上進(jìn)行查找的屬性)
const obj = {
age: 18,
name: 'A'
}
console.log(Object.getOwnPropertyDescriptors(obj))
/**
{
age: { value: 18, writable: true, enumerable: true, configurable: true },
name: { value: 'A', writable: true, enumerable: true, configurable: true }
}
**/
Object.getOwnPropertyDescriptor
獲取對(duì)象上一個(gè)自有屬性對(duì)應(yīng)的屬性描述符。
const obj = {
age: 18,
name: 'A'
}
console.log(Object.getOwnPropertyDescriptor(obj, 'age'))
// { value: 18, writable: true, enumerable: true, configurable: true }
Object.getOwnPropertyNames()
獲取指定對(duì)象的所有自身屬性的屬性名(包括不可枚舉屬性但不包括 Symbol 值作為名稱的屬性)組成的數(shù)組落追。
const obj = {
age: 18,
name: 'A',
[Symbol('address')]: 'GZ'
}
console.log(Object.getOwnPropertyNames(obj)) // [ 'age', 'name' ]
Object.getOwnPropertySymbols()
獲取指定對(duì)象自身的所有 Symbol 屬性的數(shù)組盈滴。
const obj = {
age: 18,
name: 'A',
[Symbol('address')]: 'GZ'
}
console.log(Object.getOwnPropertySymbols(obj)) // [ Symbol(address) ]
Object.hasOwn()
如果指定的對(duì)象自身有指定的屬性,返回 true
轿钠。如果屬性是繼承的或者不存在巢钓,返回 false
。
Object.assign()
將所有可枚舉的自有屬性從一個(gè)或多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象疗垛,返回修改后的對(duì)象症汹。
如果目標(biāo)對(duì)象與源對(duì)象具有相同的 key,則目標(biāo)對(duì)象中的屬性將被源對(duì)象中的屬性覆蓋贷腕,后面的源對(duì)象的屬性將類似地覆蓋前面的源對(duì)象的屬性背镇。
Object.fromEntries()
將鍵值對(duì)列表轉(zhuǎn)換為一個(gè)對(duì)象
const entries = new Map([
['name', 'abc'],
['age', 20]
])
const obj = Object.fromEntries(entries)
console.log(obj) // { name: 'abc', age: 20 }
Object.is()
Object.is()
方法判斷兩個(gè)值是否為同一個(gè)值,如果滿足以下任意條件則兩個(gè)值相等:
- 都是
undefined
- 都是
null
- 都是
true
或都是false
- 都是相同長(zhǎng)度泽裳、相同字符瞒斩、按相同順序排列的字符串
- 都是相同對(duì)象(意味著都是同一個(gè)對(duì)象的值引用)
- 都是數(shù)字且
- 都是
+0
- 都是
-0
- 都是
NaN
- 都是同一個(gè)值,非零且都不是
NaN
- 都是
Object.is()
與 ==
不同涮总。==
運(yùn)算符在判斷相等前對(duì)兩邊的變量(如果它們不是同一類型)進(jìn)行強(qiáng)制轉(zhuǎn)換(這種行為將 "" == false
判斷為 true
)胸囱,而 Object.is
不會(huì)強(qiáng)制轉(zhuǎn)換兩邊的值。
Object.is()
與 ===
也不相同瀑梗。差別是它們對(duì)待有符號(hào)的零和 NaN 不同烹笔,例如,===
運(yùn)算符(也包括 ==
運(yùn)算符)將數(shù)字 -0
和 +0
視為相等抛丽,而將 Number.NaN
與 NaN
視為不相等谤职。
Object.freeze()
凍結(jié)一個(gè)對(duì)象。
不能向這個(gè)對(duì)象添加新的屬性亿鲜,不能刪除已有屬性柬帕,不能修改該對(duì)象已有屬性的可枚舉性、可配置性狡门、可寫性嘀粱,以及不能修改已有屬性的值挺尿,對(duì)象的原型也不能被修改。
這個(gè)方法返回原對(duì)象,而不是創(chuàng)建一個(gè)被凍結(jié)的副本信卡。
如果一個(gè)屬性的值是個(gè)對(duì)象惰聂,則這個(gè)對(duì)象中的屬性是可以修改的执桌,除非它也是個(gè)凍結(jié)對(duì)象。數(shù)組作為一種對(duì)象扔仓,被凍結(jié),其元素不能被修改咖耘。沒(méi)有數(shù)組元素可以被添加或移除翘簇。
const obj = {
age: 18,
name: 'A',
address: ['GX', 'DS']
}
console.log(Object.freeze(obj) === obj)
// obj.age = 20 // 報(bào)錯(cuò)
// delete obj.age // 報(bào)錯(cuò)
obj.address.push('SS') // 可以添加
obj.address.splice(0, 1) // 可以刪除
// obj.address = [] // 報(bào)錯(cuò)
// 凍結(jié)一個(gè)數(shù)組
const arr = [1, 2, 3]
Object.freeze(arr)
arr.push(4) // 不能添加,當(dāng)然也不能做其他修改
Object.isFrozen()
判斷一個(gè)對(duì)象是否被凍結(jié)
Object.seal()
密封一個(gè)對(duì)象儿倒,阻止添加新屬性并將所有現(xiàn)有屬性標(biāo)記為不可配置版保。當(dāng)前屬性的值只要原來(lái)是可寫的就可以改變。
const obj = {
age: 18,
name: 'A'
}
Object.seal(obj)
delete obj.age // 不能刪除屬性夫否,會(huì)報(bào)錯(cuò)
// obj.age = 20 // 添加屬性彻犁,會(huì)報(bào)錯(cuò)
Object.isSealed()
判斷一個(gè)對(duì)象是否被密封。
注意凍結(jié)對(duì)象也是一個(gè)密封對(duì)象凰慈。
Object.preventExtensions()
讓一個(gè)對(duì)象變的不可擴(kuò)展汞幢,也就是永遠(yuǎn)不能再添加新的屬性。
const obj = {
age: 18,
name: 'A'
}
Object.preventExtensions(obj)
delete obj.age // 可以刪除屬性
obj.age = 20 // 添加屬性則會(huì)報(bào)錯(cuò)
Object.isExtensible()
判斷一個(gè)對(duì)象是否是可擴(kuò)展的(是否可以在它上面添加新的屬性)微谓。\n
注意凍結(jié)對(duì)象也是一個(gè)不可擴(kuò)展的對(duì)象森篷。一個(gè)不可擴(kuò)展的空對(duì)象同時(shí)也是一個(gè)凍結(jié)對(duì)象。
const obj = {
age: 18,
name: 'A'
}
Object.seal(obj)
console.log(Object.isSealed(obj)) // true
console.log(Object.isExtensible(obj)) // false密封屬性同時(shí)也是不可以拓展的
const obj1 = {}
Object.preventExtensions(obj1)
console.log(Object.isFrozen(obj1)) // true 一個(gè)不可擴(kuò)展的空對(duì)象同時(shí)也是一個(gè)凍結(jié)對(duì)象
Object.defineProperty()
語(yǔ)法:
Object.defineProperty(obj, prop, descriptor)
-
obj
:要定義屬性的對(duì)象豺型。 -
prop
:要定義或修改的屬性的名稱或 [Symbol
] -
descriptor
:要定義或修改的屬性描述符:-
value
:該屬性對(duì)應(yīng)的值仲智。可以是任何有效的JavaScript值(數(shù)值触创,對(duì)象坎藐,函數(shù)等)为牍。默認(rèn)undefined
哼绑。 -
writable
:為true
時(shí),屬性的值碉咆,也就是value
抖韩,才能被賦值運(yùn)算符改變。 默認(rèn)false
疫铜。 -
configurable
:為true
時(shí)茂浮,該屬性的描述符才能夠被改變和刪除。 默認(rèn)false
壳咕。 -
enumerable
:為true
時(shí)席揽,該屬性才會(huì)出現(xiàn)在對(duì)象的枚舉屬性中。默認(rèn)false
谓厘。 -
get
:屬性的 getter 函數(shù)幌羞,如果沒(méi)有 getter,則為undefined
竟稳。當(dāng)訪問(wèn)該屬性時(shí)属桦,會(huì)調(diào)用此函數(shù)熊痴。
執(zhí)行時(shí)不傳入任何參數(shù),但是會(huì)傳入this
對(duì)象(由于繼承關(guān)系聂宾,這里的this
并不一定是定義該屬性的對(duì)象)果善。該函數(shù)的返回值會(huì)被用作屬性的值。默認(rèn)undefined
系谐。 -
set
:屬性的 setter 函數(shù)巾陕,如果沒(méi)有 setter,則為undefined
蔚鸥。當(dāng)屬性值被修改時(shí)惜论,會(huì)調(diào)用此函數(shù)。該方法接受一個(gè)參數(shù)(也就是被賦予的新值)止喷,會(huì)傳入賦值時(shí)的this
對(duì)象馆类。 默認(rèn)為undefined
。
-
function defineReactive(obj, key, val) {
// 獲取當(dāng)前key的屬性描述符
const property = Object.getOwnPropertyDescriptor(obj, key)
if (property && property.configurable === false) {
return
}
const getter = property && property.get
const setter = property && property.set
if ((!getter || setter) && arguments.length === 2) {
val = obj[key]
}
return Object.defineProperty(obj, key, {
get() {
const value = getter ? getter.call(obj) : val
return value
},
set(newVal) {
val = newVal
}
})
}
let obj = { a: 10 }
defineReactive(obj, 'a')
console.log(obj.a)
Object.defineProperties()
在一個(gè)對(duì)象上定義新的屬性或修改現(xiàn)有屬性弹谁,并返回該對(duì)象乾巧。
let obj = {}
Object.defineProperties(obj, {
'property1': {
value: true,
writable: true
},
'property2': {
value: 'Hello',
writable: false
}
})
Object.entries()
返回一個(gè)給定對(duì)象自身可枚舉屬性的鍵值對(duì)數(shù)組,其排列與使用 for...in
循環(huán)遍歷該對(duì)象時(shí)返回的順序一致(區(qū)別在于 for-in 循環(huán)還會(huì)枚舉原型鏈中的屬性)预愤。
const obj = {
name: 'abc',
age: 18,
[{}]: 'aa',
[Symbol['address']]: 'China'
}
for (const [key, value] of Object.entries(obj)) {
console.log(`${key}: ${value}`)
}
/**
name: abc
age: 18
[object Object]: aa
undefined: China
*/
Object.keys()
返回一個(gè)由一個(gè)給定對(duì)象的自身可枚舉屬性組成的數(shù)組沟于,數(shù)組中屬性名的排列順序與使用for...in
循環(huán)的順序相同。
const obj = {
name: 'abc',
age: 18,
[{}]: 'aa',
[Symbol['address']]: 'China'
}
for (const key of Object.keys(obj)) {
console.log(key)
}
/**
name
age
[object Object]
undefined
*/
Object.values()
返回一個(gè)給定對(duì)象自身的所有可枚舉屬性值的數(shù)組植康,值的順序與使用for...in
循環(huán)的順序相同旷太。
const obj = {
name: 'abc',
age: 18,
[{}]: 'aa',
[Symbol['address']]: 'China'
}
for (const value of Object.values(obj)) {
console.log(value)
}
/**
abc
18
aa
China
*/
實(shí)例方法
Object.prototype.hasOwnProperty()
返回一個(gè)布爾值,表示對(duì)象自身屬性中是否具有指定的屬性销睁。
const parent = {
key: 'aaa'
}
const obj = Object.create(parent)
obj.age = 18
console.log(obj.age) // 18
console.log(obj.hasOwnProperty('age')) // true
console.log(obj.key) // aaa
console.log(obj.hasOwnProperty('key')) // false
// 也可以使用 Object 原型上的 hasOwnProperty 屬性
console.log(Object.prototype.hasOwnProperty.call(obj, 'age')) // true
Object.prototype.isPrototypeOf
返回一個(gè)布爾值供璧,表示一個(gè)對(duì)象是否存在于另一個(gè)對(duì)象的原型鏈上。
function Parent() {}
function Child() {}
Child.prototype = Object.create(Parent.prototype)
const child = new Child()
console.log(Parent.prototype.isPrototypeOf(child)) // true
console.log(Child.prototype.isPrototypeOf(child)) // true
console.log(Object.prototype.isPrototypeOf(child)) // true
Object.prototype.toString()
返回一個(gè)表示該對(duì)象的字符串冻记。
Object.prototype.toString()
返回 [object Type]
睡毒,這里的 Type 是對(duì)象的類型。如果對(duì)象有 Symbol.toStringTag
屬性冗栗,其值是一個(gè)字符串演顾,則它的值將被用作 Type。許多內(nèi)置的對(duì)象隅居,包括 Map
和 Symbol
钠至,都有 Symbol.toStringTag
。一些早于 ES6 的對(duì)象沒(méi)有 Symbol.toStringTag胎源,但仍然有一個(gè)特殊的標(biāo)簽棉钧。它們包括(標(biāo)簽與下面給出的類型名相同):
- Array
- Function(它的 typeof 返回 "function")
- Error
- Boolean
- Number
- String
- Date
- RegExp
console.log(Object.prototype.toString.call(1)) // [object Number]
console.log(Object.prototype.toString.call('')) // [object String]
console.log(Object.prototype.toString.call(true)) // [object Boolean]
console.log(Object.prototype.toString.call(undefined)) // [object Undefined]
console.log(Object.prototype.toString.call(null)) // [object Null]
console.log(Object.prototype.toString.call({})) // [object Object]
console.log(Object.prototype.toString.call([])) // [object Array]
console.log(Object.prototype.toString.call(function () {})) // [object Function]
console.log(Object.prototype.toString.call(new Date())) // [object Date]
console.log(Object.prototype.toString.call(new RegExp(/\d/g))) // [object RegExp]
console.log(Object.prototype.toString.call(new Error())) // [object Error]
console.log(Object.prototype.toString.call(Symbol())) // [object Symbol]
console.log(Object.prototype.toString.call(123n)) // [object BigInt]
// 自定義
let obj = {
[Symbol.toStringTag]: 'MyObj'
}
console.log(Object.prototype.toString.call(obj)) // [object MyObj]
Object.prototype.valueOf()
將 this
值轉(zhuǎn)換為一個(gè)對(duì)象。此方法旨在用于自定義類型轉(zhuǎn)換的邏輯時(shí)乒融,重寫派生類對(duì)象掰盘。
function MyNumberType(n) {
this.number = n
}
MyNumberType.prototype.valueOf = function () {
return this.number
}
const object1 = new MyNumberType(4)
console.log(object1 + 3) // 7