通過(guò)閱讀MDN,總結(jié)了一些關(guān)于Object的方法
-
Object.defineProperty(obj, prop, descriptor)
- 該方法會(huì)直接在一個(gè)對(duì)象上(obj)定義一個(gè)新屬性(prop),或者修改一個(gè)對(duì)象的現(xiàn)有屬性,并返回此對(duì)象。
- params : obj - 要傳入的對(duì)象 ,prop - 要定義或修改的屬性 ,descriptor - 要定義或修改屬性的描述符
- 關(guān)于descriptor中的get 和 set 總結(jié) - 訪問(wèn)屬性時(shí)調(diào)用get,屬性修改時(shí)調(diào)用set
-
Object.defineProperty(obj, prop, descriptor)
關(guān)于descriptor(描述符):
- configurable:
當(dāng)且僅當(dāng)該屬性的 configurable 鍵值為 true 時(shí),該屬性的描述符才能夠被改變,同時(shí)該屬性也能從對(duì)應(yīng)的對(duì)象上被刪除。
默認(rèn)為 false。
- enumerable:
enumerable定義了對(duì)象的屬性是否可以在for...in循環(huán)和Object.keys()中被枚舉。
默認(rèn)為 false。
- value:
該屬性對(duì)應(yīng)的值。可以是任何有效的 JavaScript 值(數(shù)值,對(duì)象,函數(shù)等)。
默認(rèn)為 undefined。
- writable:
當(dāng) writable 屬性設(shè)置為 false 時(shí),該屬性被稱(chēng)為“不可寫(xiě)的”。它不能被重新賦值。
默認(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。
下面以一道常見(jiàn)的面試題來(lái)當(dāng)作應(yīng)用:
var _default = 0;
Object.defineProperty(window,'a',{
get(){
return ++ _default; //get函數(shù)的返回值作為該屬性的值!
}
})
//使瀏覽器打印 'you win '
if (a === 1 && a ===2 && a === 3) {
console.log('you win')
console.log(window.a)
}
-
Object.assign(target,...sources)
- 該方法將...sources(即可以是多個(gè)對(duì)象源)中的可枚舉屬性添加到target(目標(biāo)對(duì)象)中。
-
Object.assign(target,...sources)
const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);// expected output: Object { a: 1, b: 4, c: 5 }
細(xì)節(jié)點(diǎn)1:繼承屬性和不可枚舉屬性是不能拷貝的
const obj = Object.create({foo: 1}, { // foo 是個(gè)繼承屬性。
bar: {
value: 2 // bar 是個(gè)不可枚舉屬性。
},
baz: {
value: 3,
enumerable: true // baz 是個(gè)自身可枚舉屬性。
}
});
const copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }
細(xì)節(jié)點(diǎn)2:原始類(lèi)型會(huì)被包裝成對(duì)象
const v1 = "abc";
const v2 = true;
const v3 = 10;
const v4 = Symbol("foo")
const obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
// 原始類(lèi)型會(huì)被包裝,null 和 undefined 會(huì)被忽略。
// 注意,只有字符串的包裝對(duì)象才可能有自身可枚舉屬性。
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
-
Object.create(proto,[propertiesObject])
- 方法創(chuàng)建一個(gè)新對(duì)象,使用現(xiàn)有的對(duì)象來(lái)提供新創(chuàng)建的對(duì)象的__ proto__。
- params : proto- 新創(chuàng)建對(duì)象的原型對(duì)象,[propertiesObject] - 可選,需要傳入一個(gè)對(duì)象,參考Object.defineProperty中的描述符
- return : 一個(gè)新對(duì)象,帶著指定的原型對(duì)象和屬性。
-
Object.create(proto,[propertiesObject])
我們可以使用該方法,實(shí)現(xiàn)一個(gè)兼容所有瀏覽器的繼承方法(即寄生組合式繼承)。
function Parent(){
this.x = 100;
}
parent.prototype.getX = function(){
return this.x;
}
function Child(){
//將parent中this.xxx的私有屬性拿到
parent.call(this);
this.y = 200;
}
//創(chuàng)建一個(gè)空對(duì)象x,并且把[OBJECT](這個(gè)值需要是一個(gè)對(duì)象)作為新對(duì)象的原型指向
Child.prototype = Object.create(parent.prototype)
Child.prototype.constructor = child;
Child.prototype.getY = function(){
}
-
Object.entries(obj)
- 該方法將對(duì)象轉(zhuǎn)換為數(shù)組,數(shù)組中存儲(chǔ)的是該對(duì)象可枚舉的屬性及其值
-
Object.entries(obj)
function Test() {
this.a = 1;
this.b = 2
}
Test.prototype.c = 3;
const test = new Test();
for (let k in test) {
console.log(k, test[k]);
}
// for in 會(huì)把遍歷對(duì)象的原型上的自定義屬性也遍歷出來(lái)
// 將對(duì)象轉(zhuǎn)換成數(shù)組的形式 - >可迭代 [['a',1],['b',2]]
const testArr = Object.entries(test);
for (let [k, val] of testArr) {
console.log(k, val)
}
與之相對(duì)的方法為Object.fromEntries(),該方法把鍵值對(duì)列表轉(zhuǎn)換為對(duì)象,值得注意的是在將對(duì)象用Object.entries()轉(zhuǎn)換后,再用Object.fromEntires()轉(zhuǎn)換回來(lái),和原對(duì)象用的不是同一個(gè)引用地址
-
- Object.freeze(obj)
- 凍結(jié)的對(duì)象不可修改、不可刪除、不可添加屬性,凍結(jié)后的原型不可修改。
- 特別注意不論是Object.freeze()、Object.preventExtensions()、Objext.seal(),對(duì)對(duì)象的操作都是對(duì)屬性的第一層的操作,即淺凍結(jié),上面所說(shuō)凍結(jié)后的原型不可修改指的是不可重新賦值一個(gè)新的引用地址,我們是可以對(duì)原型上的屬性進(jìn)行操作的。
- Object.defineProperty()同樣也不能對(duì)凍結(jié)后的對(duì)象進(jìn)行操作
- 方法返回值與參數(shù)obj是同一引用地址
MDN中也有寫(xiě)了對(duì)象的深度凍結(jié)
Object.deepFreeze = function (o) {
// Object.keys() //不能拿到不能枚舉的屬性
var _key = Object.getOwnPropertyNames(o)
if (_key.length) {
_key.forEach(function (k) {
var _value = o[k];
if (typeof _value === 'object' && _value !== null) {
Object.deepFreeze(_value)
}
})
}
return Object.freeze(o);
}
-
Objext.seal(obj)
- 該方法對(duì)obj進(jìn)行密封(淺密封),obj被密封后,可修改,不可刪除,不可擴(kuò)展。
- 該方法返回的是原對(duì)象的引用地址
-
Objext.seal(obj)
-
7 . Object.preventExtensions()
- 返回的obj 可修改 可刪除 不可擴(kuò)展
- Object.defineProperty() 也不能給其擴(kuò)展
-
對(duì)比 freeze seal preventExtensions
- freeze 不可修改 不可刪除 不可擴(kuò)展
- seal 可修改 不可刪除 不可擴(kuò)展
- preventExtensions 可修改 可刪除 不可擴(kuò)展
- 當(dāng)obj = {} 并且 Object.preventExtensions(obj),Object.isFrozen(obj) Object.isSealed(obj)均返回true,原因是 當(dāng)是空對(duì)象且又不可擴(kuò)展時(shí) 也滿(mǎn)足它們的判斷條件
-
8 . Object.keys(obj)
- 方法會(huì)返回一個(gè)由obj自身可枚舉屬性組成的數(shù)組,數(shù)組中屬性的排列順序和正常循環(huán)遍歷對(duì)象時(shí)的順序一致。
-
9 . Object.getOwnPropertyNames(obj)
- 返回一個(gè)數(shù)組,該數(shù)組對(duì)元素是 obj自身?yè)碛械拿杜e或不可枚舉屬性名稱(chēng)字符串。 數(shù)組中枚舉屬性的順序與通過(guò) for...in 循環(huán)迭代該對(duì)象屬性時(shí)一致。數(shù)組中不可枚舉屬性的順序未定義。
-
10 . Object.prototype.hasOwnProperty(obj)
- 方法會(huì)返回一個(gè)布爾值,指示對(duì)象自身屬性中是否具有指定的屬性(也就是,是否有指定的鍵)。