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はできません);
ジョー

これを新しい質問にするのか、ここに追加するのが理にかなっているのかわかりませんが、SymbolsとObject.freezeの間に大きな違いがあるかどうかも知りたいですか?私はそれらも関連していると感じています(つまり、シンボルはフリーズされたものとして評価されObject.isFrozenますが、独自のプリミティブデータタイプでもあります...)
Aug

1
変更は最初のレベルでのみ防止されるため、Object.freeze(x);はできません。xa = 2ですが、Object.freeze(x);はできます。XAB = 2.参照くださいjsfiddle.net/antimojv/op6ea91w/8。完全なフリーズにはアドホックライブラリを使用してください
Antimo

回答:


232

constObject.freeze2つの完全に異なるものです。

constバインディング(「変数」)に適用されます。これは不変のバインディングを作成します。つまり、バインディングに新しい値を割り当てることはできません。

Object.freeze上の作品の値、より具体的には、オブジェクト値。オブジェクトを不変にします。つまり、プロパティを変更できません。


3
基本的にconstは、新しいvarです。これは単にブロックスコープであり、再割り当てを防止します。を使用できますletが、実際に必要なのは、変数が指す値を変更する場合のみです。これは、ループ制御/反復子変数、および数値や文字列などの単純な型では意味がありますが、オブジェクトのほとんどの用途(配列)。内容を変更できないオブジェクト/配列が必要な場合は、それを宣言するほかに、それをconst呼び出す必要がありますObject.freeze()
マークリード

2
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.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 is read-only」のようなエラーをスローします。

別の使用例

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

//両方で似ていることの1つは、ネストされたオブジェクトが変更可能であることです

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

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

ありがとう。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.