<返回更多

一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法

2020-06-05    
加入收藏

一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法

 

对象冻结

这是使用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;

抛出这个:

一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法

 

浅冻结

当我们称为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之间的区别很重要。意识到这些差异将避免您在代码中使用它们时遇到麻烦。

回顾一下:

一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法

 


 
声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>