對象凍結
這是使用Object.freeze的方法:
let objectToFreeze = {
age: 28,
name: "Damien",
pets: ["Symba", "Hades", "Kiwi"],
sibling: {
age: 25,
name: "Corentin",
},
};
Object.freeze(objectToFreeze);
Object.freeze將對象作為參數。請注意,它修改了您作為參數傳遞的對象。它不會復制對象并創建一個新對象。
那么這對物體意味著什么呢?
- 您不能向對象添加新屬性
- 如果屬性本身不是對象或數組,則無法修改。(稍后會詳細介紹)
- 您不能從對象中刪除屬性
let objectToFreeze = {
age: 28,
name: "Damien",
pets: ["Symba", "Hades", "Kiwi"],
sibling: {
age: 25,
name: "Corentin",
},
};
Object.freeze(objectToFreeze);
delete objectToFreeze.age;
objectToFreeze.name = "Ben";
objectToFreeze.pets.push("Grenade");
objectToFreeze.sibling.age = 26;
objectToFreeze.lastName = "Cosset";
根據我剛才給您的描述,您應該猜測該對象現在的外觀:
console.log(objectToFreeze)
// objectToFreeze :
{ age: 28,
name: 'Damien',
pets: [ 'Symba', 'Hades', 'Kiwi', 'Grenade' ],
sibling: {
age: 25,
name: 'Corentin'
}
}
該刪除失敗,修改名稱屬性失敗并添加lastName的失敗財產。但是修改數組是可行的。
注意:如果您不在嚴格模式下,它將以靜默方式失敗。在嚴格模式下,您將收到TypeErrors
"use strict";
let objectToFreeze = {
age: 28,
name: "Damien",
pets: ["Symba", "Hades", "Kiwi"],
sibling: {
age: 25,
name: "Corentin",
},
};
Object.freeze(objectToFreeze);
delete objectToFreeze.age;
拋出這個:
淺凍結
當我們稱為Object.freeze時,我們所擁有的只是一個淺凍結。我們僅凍結直接附加到對象的對象。不關心對象和數組內部的屬性。
為了使整個對象以及其中的所有內容不可變,您必須在每個元素上調用Object.freeze()。這是您可以執行此操作的一種方法:
let allYouCanFreeze = () => {
// Retrieve the properties names
let propNames = Object.getOwnPropertyNames(obj);
// Loop through the properties
// If typeof is "object", meaning an array or object, use recursion to freeze its contents.
for (let name of propNames) {
let value = obj[name];
obj[name] =
value && typeof value === "object" ? allYouCanFreeze(value) : value;
}
// Finally, freeze the main object
return Object.freeze(obj);
};
讓我們在第一個對象上使用它:
let objectToFreeze = {
age: 28,
name: "Damien",
pets: ["Symba", "Hades", "Kiwi"],
sibling: {
age: 25,
name: "Corentin",
},
};
allYouCanFreeze(objectToFreeze);
// Now we can't touch the pets array and the sibling object
objectToFreeze.age = 26; // Now, fails.
objectToFreeze.pets.push("Grenade"); // Now, fails
大!現在,我們的兄弟對象和pets數組無法修改。
對象凍結
要知道對象是否被凍結,可以使用Object.isFrozen():
Object.isFrozen(objectToFreeze); // === true
let unfrozenObj = { a: 42 };
Object.isFrozen(unfrozenObj); // === false
物體密封
像Frozen方法一樣,Object.seal()也將對象作為參數。Object.seal是Object.freeze的較軟版本。
- 您不能刪除或向對象添加元素。
- 您可以修改現有屬性。
let objectToSeal = {
name: "Damien",
age: 28,
pets: ["Symba", "Hades", "Kiwi"],
sibling: {
age: 25,
name: "Corentin",
},
};
Object.seal(objectToSeal);
很簡單吧?讓我們現在嘗試修改該對象:
delete objectToSeal.name;
objectToSeal.age = 56;
objectToSeal.lastName = "Cosset";
objectToSeal.sibling.age = 45;
objectToSeal.pets.push("Grenade");
也許你已經猜到了應該怎么辦
//objectToSeal new contents
{
name: 'Damien',
age: 56, //modifying worked
pets: ['Symba', 'Hades', 'Kiwi', 'Grenade'], // push worked
sibling: {
age: 45, // Modifying worked
name: 'Corentin'
}
}
// adding and deleting failed!
注意,就像Object.freeze一樣,Object.seal在非嚴格模式下將靜默失敗,并在嚴格模式下引發TypeError。
對象密封
我們還有一種方法可以知道對象是否被密封。非常明確地,我們可以調用Object.isSealed來知道:
Object.isSealed(objectToSeal); // === true
let notSealedObj = { a: 54 };
Object.isSealed(notSealedObj); // === false
const呢?
您可能會想看看Object.seal和Object.freeze并將它們與const進行比較。請記住,它們是不同的概念。Object.freeze和Object.seal適用于對象的值,而const適用于binding。Object.freeze使對象不可變。const創建一個不可變的綁定。為變量分配值后,就無法為該綁定分配新值。
原型呢?
我最后要提的一件事是:原型。如果您不熟悉JAVAscript原型,我會寫一篇文章。當涉及到Object.freeze和Object.seal時,要知道一旦凍結或密封它們后就不能更改它們的原型。
let freezeThat = {
name: 'Damien'
}
let sealThis = {
age 28
}
Object.freeze(freezeThat)
Object.seal(sealThis)
// These two lines will fail!
Object.setPrototypeOf(freezeThat, {x: 26})
Object.setPrototypeOf(sealThis, {alive: true})
setPrototypeOf用于更改對象的原型。將對象密封或凍結后,您將無法執行此操作。與往常一樣,在非嚴格模式下,它將靜默失敗。在嚴格模式下,您會看到TypeError: Object is not extensible.
結論
了解Object.freeze和Object.seal之間的區別很重要。意識到這些差異將避免您在代碼中使用它們時遇到麻煩。
回顧一下:






