Object.freeze()
似乎是一种过渡性的便捷方法,可以在ES6中使用const
。
是否存在两种情况都在代码中占据一席之地,或者是否存在使用不可变数据的首选方式?
在我使用支持const
的所有浏览器之前,我应该使用Object.freeze()
,然后转而使用const
吗?
答案 0 :(得分:176)
const
和Object.freeze
是完全不同的两件事。
const
适用于绑定("变量")。它会创建一个不可变的绑定,即您无法为绑定分配新值。
Object.freeze
适用于值,更具体地说,对象值。它使一个对象不可变,即你不能改变它的属性。
答案 1 :(得分:65)
在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
答案 2 :(得分:11)
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功能创建。
答案 3 :(得分:9)
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的变量,但是我们可以对对象本身进行突变。如果我们更改现有属性或添加新属性,则将生效。要禁用对对象的任何更改,我们需要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()
在具有引用对象(例如,数组,对象)的属性时,不会完全“冻结”该对象。
答案 4 :(得分:2)
简单点吧。
它们是不同的。检查代码上的注释,它将解释每种情况。
常量-它是块范围变量,如let,其值不能重新分配,重新声明。
那是
{
const val = 10; // you can not access it out side 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 reassigning 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 reassigning 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;
谢谢。