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