2011-10-13 31 views
35

Cho một đối tượng obj, tôi muốn xác định thuộc tính chỉ đọc 'prop' và đặt giá trị của nó là val. Đây có phải là cách thích hợp để làm điều đó không?Xác định thuộc tính chỉ đọc trong JavaScript

Object.defineProperty(obj, 'prop', { 
    get: function() { 
     return val; 
    } 
}); 

Kết quả sẽ được (cho val = 'test'):

obj.prop; // 'test' 
obj.prop = 'changed'; 
obj.prop; // still 'test' since it's read-only 

Phương pháp này hoạt btw: http://jsfiddle.net/GHMjN/
Tôi chỉ không chắc chắn nếu điều này là/mượt/cách mà hầu hết thích đơn giản nhất để làm điều đó ...

+0

Có thể trùng lặp: http://stackoverflow.com/questions/366047/can-read-only-properties-be-implemented-in-pure-javascript (Nếu bạn không muốn hỗ trợ các trình duyệt cũ hơn, phương pháp của bạn là tốt nhất) –

Trả lời

64

Thay vào đó, bạn có thể sử dụng thuộc tính writable của bộ mô tả thuộc tính, ngăn chặn nhu cầu truy cập get:

var obj = {}; 
Object.defineProperty(obj, "prop", { 
    value: "test", 
    writable: false 
}); 

Đây là ECMAScript 5 vì vậy sẽ không hoạt động trong các trình duyệt cũ hơn.

+0

Tôi không chắc liệu mã của tôi và mã của bạn có tạo ra cùng một kết quả chính xác "ở bên ngoài" hay không, nhưng phương pháp của bạn không nghi ngờ gì là cách thích hợp hơn để làm điều đó. –

0

Do các trình duyệt cũ (khả năng tương thích ngược) tôi phải tìm ra các hàm truy cập cho các thuộc tính. Tôi đã tạo thành một phần của bob.js:

var obj = { }; 
//declare read-only property. 
bob.prop.namedProp(obj, 'name', 'Bob', true); 
//declare read-write property. 
bob.prop.namedProp(obj, 'age', 1); 

//get values of properties. 
console.log(bob.string.formatString('{0} is {1} years old.', obj.get_name(), obj.get_age())); 
//set value of read-write property. 
obj.set_age(2); 
console.log(bob.string.formatString('Now {0} is {1} years old.', obj.get_name(), obj.get_age())); 

//cannot set read-only property of obj. Next line would throw an error. 
// obj.set_name('Rob'); 

//Output: 
//======== 
// Bob is 1 years old. 
// Now Bob is 2 years old. 

Tôi hy vọng điều đó sẽ hữu ích.

+0

Đợi, '.namedProp (obj, 'foo')', tạo '.get_foo()',/'.set_foo()' trên chính đối tượng đó? Điều đó không hiệu quả lắm. Tôi nghĩ rằng tôi sẽ đi với một wrapper, ví dụ 'X (obj) .set ('foo')'/'X (obj) .get ('foo')'. –

+0

Để làm rõ: Tôi nghĩ chúng ta đang nói về hai điều khác nhau. Bạn có thể muốn giữ cho các đối tượng thực sự không thay đổi trong khi có một wrapper xung quanh nó; nhưng tôi đề nghị thay đổi đối tượng thực và có các hàm đại diện cho các thuộc tính. Vì tính tương thích ngược, các thuộc tính JavaScript kiểu cũ có thể được coi là các trường. Vì vậy, bạn sẽ cần phải có accessors (chức năng) cho nó (cộng với tôi sẽ đề nghị để loại bỏ các thuộc tính JS truyền thống từ các đối tượng thực sự, do đó có toàn quyền kiểm soát các thuộc tính). Về hàm bao, điều đó cũng không tệ, nhưng khác với cách tiếp cận của tôi. – Tengiz

Các vấn đề liên quan