Object.freeze () против const

136

Object.freeze()кажется переходным методом удобства перехода к использованию constв ES6.

Есть ли случаи, когда оба они занимают свое место в коде, или есть предпочтительный способ работы с неизменяемыми данными?

Следует ли мне использовать Object.freeze()до того момента, как все браузеры, с которыми я работаю, поддерживаются, а constзатем переключиться на их использование const?

Сергей Башаров
источник
2
Я начал использовать babeljs в процессе сборки, поэтому могу в основном игнорировать такие проблемы совместимости.
спонсор
22
Нет, они делают разные вещи. const предотвращает переназначение (например, вы не можете const x = 1; x = 2); замораживание предотвращает мутацию (например, вы не можете Object.freeze (x); xa = 2);
Евангелие от
Не уверен, имеет ли смысл ставить этот новый вопрос или просто задать его здесь, но мне также было бы интересно узнать, есть ли большие различия между Symbols и Object.freeze? Я чувствую, что они также связаны (т.е. символы оцениваются как замороженные, Object.isFrozenно они также являются их собственным примитивным типом данных ...)
августа
1
Мутация предотвращена только для первого уровня, поэтому вы не можете Object.freeze (x); xa = 2, но вы МОЖЕТЕ Object.freeze (x); xab = 2. См. jsfiddle.net/antimojv/op6ea91w/8 . Для полного замораживания используйте специальные библиотеки
Antimo

Ответы:

234

constи Object.freezeэто две совершенно разные вещи.

constприменяется к привязкам («переменным»). Он создает неизменяемую привязку, т. Е. Привязке нельзя присвоить новое значение.

Object.freezeработает со значениями , а более конкретно - со значениями объектов . Это делает объект неизменным, т.е. вы не можете изменить его свойства.

Феликс Клинг
источник
3
В основном, constэто новое var; это просто блок-область и предотвращает переназначение. Вы можете использовать let, но на самом деле это необходимо только в том случае, если вы собираетесь изменить значение, на которое указывает переменная, что имеет смысл для переменных управления циклом / итератора и простых типов, таких как числа и строки, но не для большинства видов использования объектов (включая массивы). Если вам нужен объект / массив, содержимое которого не может быть изменено, constвы должны не только объявить его, но и вызвать Object.freeze()его.
Марк Рид
2
constЭто НЕ новый var, letэто новыйvar
Факундо Коломбье
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
Pawel
источник
Это объяснение сняло так много моих вопросов одним махом! Относительно ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested: Это из-за области применения метода?
YCode
14

Резюме:

constи Object.freeze()служат совершенно разным целям.

  • constсуществует для объявления переменной, которая должна быть задействована сразу и не может быть переназначена. переменные, объявленные с помощью, constимеют область видимости блока, а не функцию, как переменные, объявленные с помощьюvar
  • Object.freeze()- это метод, который принимает объект и возвращает тот же объект. Теперь нельзя удалить какие-либо свойства объекта или добавить какие-либо новые свойства.

Примеры const:

Пример 1. Невозможно переназначить const

const foo = 5;

foo = 6;

Следующий код вызывает ошибку, потому что мы пытаемся переназначить переменную foo, которая была объявлена ​​с constключевым словом, мы не можем переназначить ее.

Пример 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()образом, объект не «замораживается» полностью, если он имеет свойства, являющиеся ссылками (например, на массивы, объекты).

Виллем ван дер Веен
источник
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
};

Это вызовет ошибку типа «объект только для чтения».

Другой вариант использования

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;

Спасибо.

Химаншу Шарма
источник