Object.freeze () vs const

146

Object.freeze()wydaje się być przejściową wygodną metodą przejścia do stosowania constw ES6.

Czy są przypadki, w których oba zajmują swoje miejsce w kodzie lub czy istnieje preferowany sposób pracy z niezmiennymi danymi?

Czy powinienem używać Object.freeze()wszystkich przeglądarek, z którymi współpracuję, a constpotem przełączyć się na ich używanie const?

Siergiej Baszarow
źródło
2
Zacząłem używać babeljs w moim procesie budowania, więc mogę głównie ignorować takie problemy ze zgodnością.
wydający
25
Nie - robią różne rzeczy. const zapobiega zmianie przypisania (np. nie możesz const x = 1; x = 2); freeze zapobiega mutacji (np. nie możesz Object.freeze (x); xa = 2);
joews
Nie jestem pewien, czy sensowne jest uczynienie tego nowego pytania, czy po prostu dodanie go tutaj, ale byłbym również ciekawy, czy są jakieś duże różnice między Symbols i Object.freeze? Czuję się one również związane (tj Symbole są oceniane jako zamrożone od Object.isFrozenale także są one ich własne prymitywny typ danych ...)
sierpień
2
Mutacja jest zablokowana tylko na pierwszym poziomie, więc nie możesz Object.freeze (x); xa = 2, ale MOŻESZ Object.freeze (x); xab = 2. Zobacz jsfiddle.net/antimojv/op6ea91w/8 . Aby całkowicie zamrozić, użyj bibliotek ad hoc
Antimo

Odpowiedzi:

251

consti Object.freezeto dwie zupełnie różne rzeczy.

constdotyczy powiązań („zmiennych”). Tworzy niezmienne powiązanie, tj. Nie można przypisać nowej wartości do powiązania.

Object.freezedziała na wartościach , a dokładniej na wartościach obiektów . Czyni obiekt niezmiennym, tj. Nie można zmienić jego właściwości.

Felix Kling
źródło
3
Zasadniczo constjest nowy var; ma tylko zasięg blokowy i zapobiega zmianie przypisania. Możesz użyć let, ale naprawdę musisz to zrobić tylko wtedy, gdy zamierzasz zmienić wartość, na którą wskazuje zmienna, co ma sens w przypadku zmiennych sterujących pętlą / iteratorów i prostych typów, takich jak liczby i łańcuchy, ale nie w przypadku większości zastosowań obiektów (w tym tablice). Jeśli chcesz mieć obiekt / tablicę, której zawartość nie może być zmieniona, to oprócz zadeklarowania go constpowinieneś również wywołać Object.freeze()go.
Mark Reed
4
constNIE jest nowy var, letjest nowyvar
Facundo Colombier
88

W ES5 Object.freezenie działa na prymitywach, które prawdopodobnie byłyby częściej deklarowane przy użyciu constniż obiektów. Możesz zamrażać prymitywy w ES6, ale masz też wsparcie dla const.

Z drugiej strony constdeklarowanie obiektów nie "zamraża" ich, po prostu nie możesz ponownie zadeklarować całego obiektu, ale możesz dowolnie modyfikować jego klucze. Z drugiej strony możesz ponownie deklarować zamrożone obiekty.

Object.freeze jest również płytka, więc trzeba by ją rekurencyjnie stosować do obiektów zagnieżdżonych, aby je chronić.

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
Paweł
źródło
To wyjaśnienie rozwiązało tak wiele moich pytań za jednym zamachem! Dotyczy ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested: Czy wynika to z zakresu metody?
YCode
15

Podsumowanie:

consti Object.freeze()służą zupełnie innym celom.

  • constsłuży do deklarowania zmiennej, która musi zostać przypisana od razu i nie może być ponownie przypisana. zmienne zadeklarowane przez constmają zakres blokowy, a nie zakres funkcji, jak zmienne zadeklarowane za pomocąvar
  • Object.freeze()jest metodą, która akceptuje obiekt i zwraca ten sam obiekt. Teraz nie można usunąć żadnych właściwości obiektu ani dodać nowych właściwości.

Przykłady const:

Przykład 1: nie można ponownie przypisać const

const foo = 5;

foo = 6;

Poniższy kod zgłasza błąd, ponieważ próbujemy ponownie przypisać zmienną foo, która została zadeklarowana za pomocą constsłowa kluczowego, nie możemy jej ponownie przypisać.

Przykład 2: Struktury danych, do których są przypisane, constmożna modyfikować

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

W tym przykładzie deklarujemy zmienną za pomocą constsłowa kluczowego i przypisujemy do niej obiekt. Chociaż nie możemy ponownie przypisać tej zmiennej o nazwie object, możemy zmutować sam obiekt. Jeśli zmienimy istniejące właściwości lub dodamy nowe właściwości, będzie to miało skutek. Aby wyłączyć wszelkie zmiany w obiekcie, których potrzebujemy Object.freeze().

Przykłady Object.freeze():

Przykład 1: Nie można zmutować zamrożonego obiektu

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

W tym przykładzie, gdy wywołujemy Object.freeze()i podajemy object1jako argument, funkcja zwraca obiekt, który jest teraz „zamrożony”. Jeśli porównamy odniesienie nowego obiektu do starego obiektu za pomocą ===operatora, możemy zauważyć, że odnoszą się one do tego samego obiektu. Również, gdy próbujemy dodać lub usunąć jakiekolwiek właściwości, widzimy, że nie ma to żadnego efektu (w trybie ścisłym pojawi się błąd).

Przykład 2: Obiekty z odniesieniami nie są w pełni zamrożone

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);

Ten przykład pokazuje, że właściwości obiektów zagnieżdżonych (i innych przez referencyjne struktury danych) są nadal modyfikowalne . Więc Object.freeze()nie „zamraża” w pełni obiektu, gdy ma właściwości, które są referencjami (np. Tablice, obiekty).

Willem van der Veen
źródło
12
var obj = {
  a: 1,
  b: 2
};
Object.freeze(obj);
obj.newField = 3; // You can't assign new field , or change current fields

Powyższy przykład całkowicie czyni twój obiekt niezmiennym.

Spójrzmy na następujący przykład.

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

To nie da żadnego błędu.

Ale jeśli spróbujesz w ten sposób

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

Zostanie wyświetlony błąd taki jak „obj jest tylko do odczytu”.

Inny przypadek użycia

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

Będzie rzucać Duplicate declaration "obj"

Również zgodnie z wyjaśnieniem mozilla docs const

Deklaracja const tworzy odwołanie tylko do odczytu do wartości. Nie oznacza to, że wartość, którą posiada, jest niezmienna , a jedynie, że nie można ponownie przypisać identyfikatora zmiennej.

Te przykłady zostały utworzone zgodnie z funkcjami babeljs ES6.

İlker Korkut
źródło
6

Niech będzie proste.

Oni są różni. Sprawdź komentarze do kodu, które wyjaśnią każdy przypadek.

Const- Jest to zmienna o zasięgu blokowym let, której wartość nie może zostać ponownie przypisana, ponownie zadeklarowana.

To znaczy

{
 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

Rozumie się, że const ma zasięg blokowy, a jego wartość nie jest ponownie przypisywana.

Object.freeze: Właściwości katalogu głównego obiektu są niezmienne, również nie możemy dodawać i usuwać więcej właściwości, ale możemy ponownie przypisać cały obiekt.

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

// Jedna rzecz, która jest podobna w obu przypadkach, to fakt, że zagnieżdżone obiekty są zmienne

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

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

Dzięki.

Himanshu sharma
źródło