Object.freeze()与const


136

Object.freeze()似乎是过渡到constES6中使用的一种过渡便利方法。

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

我应该使用Object.freeze()直到支持的所有浏览器都const转而使用const


2
我已经在构建过程中使用了babeljs,所以我主要可以忽略诸如此类的兼容性问题。
支出者,2015年

22
不-他们做不同的事情。const防止重新分配(例如,您不能const x = 1; x = 2);冻结可防止突变(例如,您不能Object.freeze(x); xa = 2);
乔斯(Joews)2015年

不知道是一个新问题还是在这里解决这个问题是否有意义,但我也想知道,Symbols和Object.freeze之间是否存在较大差异?我觉得他们也有关系(即符号被评估为从冷冻Object.isFrozen,但他们也有自己的原始数据类型...)
八月

仅在第一级阻止该突变,因此您不能Object.freeze(x);。xa = 2,但是您可以Object.freeze(x); xab =2。请参阅jsfiddle.net/antimojv/op6ea91w/8。要完全冻结,请使用临时库
Antimo

Answers:


229

constObject.freeze是完全不同的两件事。

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

Object.freeze处理,更具体地说,处理对象值。它使对象不可变,即您不能更改其属性。


3
基本上const是新的var;它只是块作用域,可以防止重新分配。您可以使用let,但实际上仅在要更改变量指向的值时才需要使用,这对于循环控制/迭代器变量以及简单的类型(例如数字和字符串)有意义,但对于大多数对象使用(包括数组)。如果您想要一个对象/数组,其内容不能更改,那么除了用它声明以外,const还应该对其进行调用Object.freeze()
马克·里德

1
const不是新的varlet不是新的var
Facundo Colombier

84

在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

这一解释一口气清除了我的许多问题!关于ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested:是否因为方法的范围?
YCode

14

摘要:

constObject.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的变量,但是我们可以对对象本身进行突变。如果我们更改现有属性或添加新属性,则将生效。要禁用对对象的任何更改,我们需要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(),当对象具有作为引用的属性(例如,数组,对象)时,不会完全“冻结”该对象。


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为只读”的错误。

另一个用例

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

它将抛出 Duplicate declaration "obj"

也根据mozilla docs const的解释

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

此示例根据babeljs ES6功能创建。


4

简单一点。

它们不一样。检查代码上的注释,这将解释每种情况。

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;

谢谢。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.