这是使用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
您可能会想看看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之间的区别很重要。意识到这些差异将避免您在代码中使用它们时遇到麻烦。
回顾一下: