Object.freeze () vs const


136

Object.freeze()представляється перехідним методом зручності для переходу до використання constв ES6.

Чи бувають випадки, коли обидва займають своє місце в коді або є кращий спосіб роботи з незмінними даними?

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


2
Я брав до використання babeljs в процесі збирання, тому я в основному можу ігнорувати такі проблеми сумісності, як ці.
шендер

22
Ні - вони роблять різні речі. const запобігає переназначенню (наприклад, ви не можете const x = 1; x = 2); заморожування запобігає мутації (наприклад, ви не можете Object.freeze (x); xa = 2);
Joews

Не впевнений, чи є сенс ставити це питання новим питанням або просто вирішувати його тут, але мені також цікаво, якщо між символами та Object.freeze є великі відмінності? Я відчуваю , що вони також пов'язані (тобто символи оцінюються як заморожені з , Object.isFrozenале вони також є їх власним примітивним тип даних ...)
серпня

1
Мутація запобігається лише на першому рівні, тому ви не можете Object.freeze (x); xa = 2, але ви МОЖЕТЕ Object.freeze (x); xab = 2. Див. jsfiddle.net/antimojv/op6ea91w/8 . Для повного заморожування використовуйте спеціальні бібліотеки
Antimo

Відповіді:


232

constі Object.freezeце дві абсолютно різні речі.

constстосується прив'язок ("змінних"). Це створює незмінне зв'язування, тобто ви не можете присвоїти нове значення прив'язці.

Object.freezeпрацює на значення , а точніше, на об'єктні значення . Це робить об'єкт незмінним, тобто ви не можете змінити його властивості.


3
В основному, constце нове var; це просто блокчейн та запобігає перепризначенню. Ви можете використовувати let, але насправді це потрібно лише в тому випадку, якщо ви збираєтеся змінити значення, на яке вказує змінна, що має сенс для змінних змін / ітераторів змін та простих типів, таких як числа та рядки, але не для більшості застосувань об'єктів (у т.ч. масиви). Якщо ви хочете об'єкт / масив, вміст якого неможливо змінити, окрім декларування його з constвами, слід також зателефонувати Object.freeze()на нього.
Марк Рід

2
constНЕ нове var, letнове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

Підсумок:

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

  • constє для оголошення змінної, яка повинна відразу ж перейти в режим assinged і не може бути перепризначена. змінні, задекларовані 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
};

Це призведе до помилки типу "obj є лише для читання".

Ще один випадок використання

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

Це кине Duplicate declaration "obj"

Крім того, згідно з документами мозілла 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;

Дякую.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.