Object.freeze() 与 const

问题描述 投票:0回答:6

Object.freeze()
似乎是在 ES6 中使用
const
的过渡便捷方法。

是否存在两者都在代码中占据一席之地的情况,或者是否有处理不可变数据的首选方法?

我应该使用

Object.freeze()
直到我使用的所有浏览器都支持
const
然后改用
const
吗?

javascript ecmascript-6
6个回答
323
投票

const
Object.freeze
是完全不同的两个东西。

const
适用于 绑定(“变量”)。它创建一个不可变的绑定,即您无法为该绑定分配新值。

Object.freeze
适用于,更具体地说,适用于对象值。它使对象不可变,即您无法更改其属性。


114
投票

在 ES5 中,

Object.freeze
不适用于基元,与对象相比,使用
const
可能更常见地声明基元。您可以在 ES6 中冻结原语,但您还可以支持
const

另一方面,用于声明对象的

const
不会“冻结”它们,你只是不能重新声明整个对象,但你可以自由修改它的键。另一方面,您可以重新声明冻结的对象。

Object.freeze
也很浅,因此您需要递归地将其应用于嵌套对象以保护它们。

var ob1 = {
   foo : 1,
    bar : {
        value : 2   
    }
};
Object.freeze( ob1 );

const ob2 = {
   foo : 1,
    bar : {
        value : 2   
    }
}

ob1.foo = 4;  // (frozen) ob1.foo not modified
ob2.foo = 4;  // (const) ob2.foo modified

ob1.bar.value = 4;  // (frozen) modified, because ob1.bar is nested
ob2.bar.value = 4;  // (const) modified

ob1.bar = 4;  // (frozen) not modified, bar is a key of obj1
ob2.bar = 4;  // (const) modified

ob1 = {};  // (frozen) ob1 redeclared
ob2 = {}; // (const) ob2 not redeclared

34
投票

总结:

const
Object.freeze()
具有完全不同的用途。

  • const
    用于声明必须立即分配且无法重新分配的变量。由
    const
    声明的变量是块作用域,而不是像用
    var
  • 声明的变量一样是函数作用域
  • Object.freeze()
    是一种接受对象并返回相同对象的方法。现在,该对象无法删除其任何属性或添加任何新属性。

示例
const

示例1:无法重新分配

const

const foo = 5;

foo = 6;

下面的代码会抛出错误,因为我们试图重新分配使用

const
关键字声明的变量 foo,但我们无法重新分配它。

示例 2:分配给

const
的数据结构可以改变

const object = {
  prop1: 1,
  prop2: 2 
}

object.prop1 = 5;   // object is still mutable!
object.prop3 = 3;   // object is still mutable!

console.log(object);  // object is mutated

在此示例中,我们使用

const
关键字声明一个变量并为其分配一个对象。虽然我们不能重新分配给这个称为对象的变量,但我们可以改变对象本身。如果我们更改现有属性或添加新属性,这将会生效。要禁用对对象的任何更改,我们需要
Object.freeze()

示例
Object.freeze()

示例 1:无法改变冻结的对象

object1 = {
  prop1: 1,
  prop2: 2
}

object2 = Object.freeze(object1);

console.log(object1 === object2); // both objects are refer to the same instance

object2.prop3 = 3; // no new property can be added, won't work

delete object2.prop1; // no property can be deleted, won't work

console.log(object2); // object unchanged

在此示例中,当我们调用

Object.freeze()
并将
object1
作为参数时,函数返回现在“冻结”的对象。如果我们使用
===
运算符将新对象的引用与旧对象的引用进行比较,我们可以观察到它们引用的是同一个对象。此外,当我们尝试添加或删除任何属性时,我们可以看到这没有任何效果(在严格模式下会抛出错误)。

示例 2:具有引用的对象未完全冻结

const object = {
  prop1: 1,
  nestedObj: {
    nestedProp1: 1,
    nestedProp2: 2,
  } 
}


const frozen = Object.freeze(object);

frozen.prop1 = 5; // won't have any effect
frozen.nestedObj.nestedProp1 = 5; //will update because the nestedObject isn't frozen

console.log(frozen);

此示例表明嵌套对象(以及其他引用数据结构)的属性仍然可变。因此,当对象具有引用的属性(例如数组、对象)时,

Object.freeze()
不会完全“冻结”对象。


14
投票

简单点吧。

他们是不同的。检查代码上的注释,这将解释每种情况。

Const
- 它是块范围变量,如
let
,其值不能重新分配、重新声明。

这意味着

{
 const val = 10;  // you can not access it outside this block, block scope variable

}

console.log(val); // undefined because it is block scope 

const constvalue = 1;
constvalue = 2; // will give error as we are re-assigning the value;
const obj = { a:1 , b:2};

obj.a = 3;
obj.c = 4;
console.log(obj); // obj = {a:3,b:2,c:4} we are not assigning the value of identifier we can 
                  // change the object properties, const applied only on value, not with properties
obj = {x:1};     // error you are re-assigning the value of constant obj 
obj.a = 2 ;     // you can add, delete element of object

整体理解是const是块作用域,并且它的值不会被重新赋值。

Object.freeze
: 对象根属性是不可更改的,我们也不能添加和删除更多属性,但我们可以再次重新分配整个对象。

var x = Object.freeze({data:1,
    name:{
    firstname:"hero", lastname:"nolast"
    }
});

x.data = 12;  // the object properties can not be change but in const you can do
x.firstname ="adasd"; // you can not add new properties to object but in const you can do

x.name.firstname = "dashdjkha"; // The nested value are changeable 

//The thing you can do in Object.freeze but not in const

x = { a: 1};  // you can reassign the object when it is Object.freeze but const its not allowed

// 两者相似的一件事是,嵌套对象是可变的

const obj1 = {nested :{a:10}};
var obj2 =  Object.freeze({nested :{a:10}});

obj1.nested.a = 20; // both statement works
obj2.nested.a = 20;

谢谢。


12
投票
var obj = {
  a: 1,
  b: 2
};
Object.freeze(obj);
obj.newField = 3; // You can't assign new field , or change current fields

上面的例子完全使你的对象不可变。

让我们看看下面的例子。

const obj = {
  a: 1,
  b: 2
};
obj.a = 13; // You can change a field
obj.newField = 3; // You can assign new field.

不会出现任何错误。

但是如果你这样尝试

const obj = {
      a: 1,
      b: 2
    };
obj = {
 t:4
};

它会抛出类似“obj is read-only”的错误。

另一个用例

const obj = {a:1};
var obj = 3;

它会抛出

Duplicate declaration "obj"

也根据 mozilla 文档 const 解释

const 声明创建对值的只读引用。 它 并不意味着它所持有的价值是不可变的,只是 变量标识符不能重新分配。

这个例子是根据babeljs ES6特性创建的。


0
投票

在 ES6 中 const 比以前更常用,你不能用另一个值再次定义它,你会遇到错误,另一方面,如果你冻结一个对象,你不能再次更改或定义它的属性,你会再次面临错误

© www.soinside.com 2019 - 2024. All rights reserved.