Object.freeze () vs const


136

Object.freeze()có vẻ như là một phương pháp thuận tiện chuyển tiếp để chuyển sang sử dụng consttrong ES6.

Có trường hợp nào cả hai thay thế vị trí của chúng trong mã hoặc có cách nào ưu tiên để làm việc với dữ liệu không thay đổi?

Tôi có nên sử dụng Object.freeze()cho đến thời điểm tất cả các trình duyệt tôi làm việc có hỗ trợ constsau đó chuyển sang sử dụng constkhông?


2
Tôi đã sử dụng babeljs trong quá trình xây dựng của mình để tôi chủ yếu có thể bỏ qua các vấn đề tương thích như các vấn đề này.
tiêu

22
Không - họ làm những việc khác nhau. const ngăn chặn việc gán lại (ví dụ: bạn không thể const x = 1; x = 2); đóng băng ngăn ngừa đột biến (ví dụ: bạn không thể Object.freeze (x); xa = 2);
tham gia

Không chắc có ý nghĩa gì khi biến câu hỏi này thành một câu hỏi mới hay chỉ giải quyết nó ở đây nhưng tôi cũng sẽ tò mò liệu có sự khác biệt lớn nào giữa Symbols và Object.freeze không? Tôi cảm thấy họ cũng có liên quan (ví dụ: Biểu tượng được đánh giá là đông lạnh từ Object.isFrozennhưng họ cũng là của riêng nguyên thủy kiểu dữ liệu của họ ...)
Tháng Tám

Đột biến chỉ được ngăn chặn ở cấp độ đầu tiên để bạn không thể Object.freeze (x); xa = 2, nhưng bạn CÓ THỂ Object.freeze (x); xab = 2. Xem jsfiddle.net/antimojv/op6ea91w/8 . Để đóng băng hoàn toàn, hãy sử dụng các thư viện ad hoc
Antimo

Câu trả lời:


229

constObject.freezelà hai điều hoàn toàn khác nhau.

constáp dụng cho các ràng buộc ("biến"). Nó tạo ra một ràng buộc bất biến, tức là bạn không thể gán một giá trị mới cho liên kết.

Object.freezehoạt động trên các giá trị , và cụ thể hơn, các giá trị đối tượng . Nó làm cho một đối tượng bất biến, tức là bạn không thể thay đổi thuộc tính của nó.


3
Về cơ bản, constlà cái mới var; nó chỉ nằm trong phạm vi khối và ngăn chặn việc gán lại. Bạn có thể sử dụng let, nhưng thực sự chỉ cần nếu bạn sẽ thay đổi giá trị mà một biến chỉ ra, điều này có ý nghĩa đối với các biến điều khiển vòng lặp / biến lặp và các loại đơn giản như số và chuỗi, nhưng không phải cho hầu hết việc sử dụng các đối tượng (bao gồm mảng). Nếu bạn muốn một đối tượng / mảng có nội dung không thể thay đổi, thì ngoài việc khai báo nó với constbạn, bạn cũng nên gọi Object.freeze()nó.
Mark Reed

1
constKHÔNG phải là mới var, letlà mớivar
Facundo Colombiaier

84

Trong ES5 Object.freezekhông hoạt động trên các nguyên thủy, có lẽ sẽ được khai báo phổ biến consthơn sử dụng so với các đối tượng. Bạn có thể đóng băng nguyên thủy trong ES6, nhưng sau đó bạn cũng có hỗ trợ const.

Mặt khác, constđược sử dụng để khai báo các đối tượng không "đóng băng" chúng, bạn không thể xác định lại toàn bộ đối tượng, nhưng bạn có thể sửa đổi các khóa của nó một cách tự do. Mặt khác, bạn có thể xác định lại các đối tượng đông lạnh.

Object.freeze cũng nông, vì vậy bạn cần áp dụng đệ quy nó lên các đối tượng lồng nhau để bảo vệ chúng.

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

Giải thích này đã xóa rất nhiều câu hỏi của tôi trong một lần quét! Về ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested: Có phải vì phạm vi của phương pháp?
YCode

14

Tóm lược:

constObject.freeze()phục vụ các mục đích hoàn toàn khác nhau.

  • constcó để khai báo một biến phải xác nhận ngay và không thể được chỉ định lại. các biến được khai báo bởi constkhối có phạm vi và không có phạm vi chức năng như các biến được khai báo bằngvar
  • Object.freeze()là một phương thức chấp nhận một đối tượng và trả về cùng một đối tượng. Bây giờ đối tượng không thể xóa bất kỳ thuộc tính nào của nó hoặc bất kỳ thuộc tính mới nào được thêm vào.

Ví dụ const:

Ví dụ 1: Không thể gán lại const

const foo = 5;

foo = 6;

Đoạn mã sau đưa ra lỗi vì chúng tôi đang cố gắng gán lại biến foo đã được khai báo bằng consttừ khóa, chúng tôi không thể gán lại nó.

Ví dụ 2: Cấu trúc dữ liệu được gán cho constcó thể bị đột biến

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

Trong ví dụ này, chúng tôi khai báo một biến bằng cách sử dụng consttừ khóa và gán một đối tượng cho nó. Mặc dù chúng ta không thể gán lại cho biến được gọi là đối tượng này, chúng ta có thể tự biến đổi đối tượng. Nếu chúng ta thay đổi các thuộc tính hiện có hoặc thêm các thuộc tính mới thì điều này sẽ có hiệu lực. Để vô hiệu hóa bất kỳ thay đổi đối với đối tượng chúng ta cần Object.freeze().

Ví dụ Object.freeze():

Ví dụ 1: Không thể biến đổi một đối tượng đông lạnh

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

Trong ví dụ này khi chúng ta gọi Object.freeze()và đưa ra object1như một đối số, hàm trả về đối tượng hiện bị 'đóng băng'. Nếu chúng ta so sánh tham chiếu của đối tượng mới với đối tượng cũ bằng ===toán tử, chúng ta có thể quan sát rằng chúng tham chiếu đến cùng một đối tượng. Ngoài ra khi chúng tôi cố gắng thêm hoặc xóa bất kỳ thuộc tính nào, chúng tôi có thể thấy rằng điều này không có bất kỳ ảnh hưởng nào (sẽ ném lỗi trong chế độ nghiêm ngặt).

Ví dụ 2: Các đối tượng có tham chiếu không bị đóng băng hoàn toàn

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

Ví dụ này cho thấy các thuộc tính của các đối tượng lồng nhau (và khác bởi các cấu trúc dữ liệu tham chiếu) vẫn có thể thay đổi . Vì vậy, Object.freeze()không hoàn toàn 'đóng băng' đối tượng khi nó có các thuộc tính là tham chiếu (ví dụ: Mảng, Đối tượng).


12
var obj = {
  a: 1,
  b: 2
};
Object.freeze(obj);
obj.newField = 3; // You can't assign new field , or change current fields

Ví dụ trên nó hoàn toàn làm cho đối tượng của bạn bất biến.

Hãy xem ví dụ sau đây.

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

Nó sẽ không đưa ra bất kỳ lỗi nào.

Nhưng nếu bạn cố gắng như thế

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

Nó sẽ đưa ra một lỗi như thế "obj là chỉ đọc".

Trường hợp sử dụng khác

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

Nó sẽ ném Duplicate declaration "obj"

Cũng theo tài liệu mozilla const lời giải thích

Khai báo const tạo một tham chiếu chỉ đọc đến một giá trị. Điều đó không có nghĩa là giá trị mà nó giữ là không thay đổi , chỉ có thể xác định lại định danh biến.

Ví dụ này được tạo theo các tính năng ES6 của babeljs.


4

Hãy đơn giản.

Họ khác nhau. Kiểm tra các ý kiến ​​về mã, điều đó sẽ giải thích từng trường hợp.

Const- Đó là biến phạm vi khối như let, giá trị nào không thể gán lại, khai báo lại.

Điều đó có nghĩa là

{
 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

Toàn bộ sự hiểu biết là const là phạm vi khối và giá trị của nó không được gán lại.

Object.freeze: Các thuộc tính gốc của đối tượng là không thể thay đổi, chúng tôi cũng không thể thêm và xóa thêm các thuộc tính nhưng chúng tôi có thể gán lại toàn bộ đối tượng một lần nữa.

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

// Một điều tương tự ở cả hai là, đối tượng lồng nhau có thể thay đổi

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

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

Cảm ơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.