2012-06-01 45 views
25

Làm cách nào các hằng số không thể được đặt làm thuộc tính của các đối tượng là các biến?Cách tạo hằng số Javascript làm thuộc tính của đối tượng bằng cách sử dụng từ khóa const?

const a = 'constant' // all is well 
// set constant property of variable object 
const window.b = 'constant' // throws Exception 
// OR 
var App = {}; // want to be able to extend 
const App.goldenRatio= 1.6180339887 // throws Exception 

Và cách hằng số được chuyển qua tham chiếu đột nhiên trở thành biến? EDIT: Tôi biết Ứng dụng sẽ không (hoặc đúng hơn ... KHÔNG NÊN) có thể thay đổi; đây chỉ là một quan sát ...

(function() { 
    const App; 
    // bunch of code 
    window.com_namespace = App; 
}()); 
window.com_namespace; // App 
window.com_namespace = 'something else'; 
window.com_namespace; // 'something else' 

Làm thế nào một thư viện có tên, có thể mở rộng, hướng đối tượng, đơn lẻ có chứa hằng số được thực hiện với những giới hạn này?

EDIT: Tôi tin zi42, nhưng tôi chỉ phải hỏi why

Trả lời

33

Bạn không thể làm điều đó với các hằng số. Cách duy nhất có thể làm điều gì đó mà cư xử như bạn muốn, nhưng không được sử dụng các hằng số, là để xác định một tài sản phi thể ghi:

var obj = {}; 
Object.defineProperty(obj, "MY_FAKE_CONSTANT", { 
    value: "MY_FAKE_CONSTANT_VALUE", 
    writable: false, 
    enumerable: true, 
    configurable: true 
}); 

Về câu hỏi của bạn là tại sao một const truyền cho một chức năng trở nên biến, câu trả lời là bởi vì nó được truyền theo giá trị chứ không phải bằng tham chiếu. Hàm này nhận được một biến mới có cùng giá trị với hằng số của bạn.

chỉnh sửa: nhờ @pst cho lưu ý rằng đối tượng literals trong javascript không thực sự "thông qua tham khảo", nhưng sử dụng call-by-sharing:

Mặc dù thuật ngữ này có sử dụng rộng rãi trong cộng đồng Python, giống hệt nhau ngữ nghĩa trong các ngôn ngữ khác như Java và Visual Basic thường được mô tả là giá trị theo từng giá trị, trong đó giá trị được ngụ ý là tham chiếu đến đối tượng.

+0

Đối tượng không được truyền bằng tham chiếu? – danronmoon

+0

Có, nhưng 'const obj = {}' là kinda vô ích vì tham chiếu sẽ không đổi, nhưng bạn vẫn có thể sửa đổi đối tượng. –

+4

Không. Đối tượng là * không * "được chuyển bởi tham chiếu" (đây là cụm từ mơ hồ nhất). Một thực hiện thường sẽ "vượt qua * giá trị * của tài liệu tham khảo" nhưng điều quan trọng là JavaScript có [Gọi theo ngữ nghĩa chia sẻ đối tượng] (http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing). Thực tế thú vị: * đặc tả ECMAScript không sử dụng thuật ngữ "tham chiếu" *. –

3
const person = { 
    name: "Nicholas" 
}; 

// works 
person.name = "Greg"; 



console.log(person) //Greg 

Đó là lý do tại sao sử dụng Object.defineProperty

1

Bạn không nên quên hơn const declaration "tạo ra một tham chiếu chỉ đọc đến một giá trị. Nó không có nghĩa là giá trị nó giữ là không thay đổi, chỉ là tên biến không thể được bố trí"

công việc từ khóa const trong một cách tương tự hơn 'let', vì vậy bạn có thể redeclare nó trong một khối khác

const MyConst = 5; 
console.log('global MyConst =', MyConst); //global MyConst = 5 
if(true){ 
    const MyConst = 99 
    console.log('in if block, MyConst =', MyConst); //in if block, MyConst = 99 
} 
console.log('global MyConst still 5 ?', MyConst===5); //global MyConst still 5 ? true 

Giống như @ ziad-saab được gắn nếu bạn muốn một thuộc tính đối tượng hơn là hành động như một hằng số, bạn phải xác định nó là thuộc tính không thể ghi.

nếu hằng số của bạn là một đối tượng và thuộc tính không được thay đổi, hãy sử dụng Object.freeze() để làm cho đối tượng không thay đổi được.

(function(){ 
    var App = { }; 
    // create a "constant" object property for App 
    Object.defineProperty(App , "fixedStuff", { 
    value: Object.freeze({ prop:6 }), 
    writable: false, 
    enumerable: true, 
    configurable: true 
    }); 

    Object.defineProperty(window, "com_namespace", { 
    value: App, 
    writable: false, 
    enumerable: true, 
    configurable: true 
    }); 
})() 

com_namespace.newStuff = 'An extension'; 
com_namespace.fixedStuff.prop = 'new value'; // do nothing! 
console.log(com_namespace.fixedStuff.prop); //6 
3

Có cách đơn giản hơn rất nhiều để thực hiện việc này. Tôi thích kiểu này. Đối tượng đơn giản.

window.Thingy = (function() { 

    const staticthing = "immutable"; 

    function Thingy() { 

     let privateStuff = "something"; 

     function get() { 
      return privateStuff; 
     } 

     function set(_) { 
      privateStuff = _; 
     } 
     return Object.freeze({ 
      get, 
      set, 
      staticthing 
     }); 
    } 

    Thingy.staticthing = staticthing; 
    return Object.freeze(Thingy); 
})(); 

let myThingy = new Thingy(); 

Thingy.staticthing = "fluid"; 

myThingy.staticthing = "fluid"; 

console.log(Thingy.staticthing); // "immutable" 
console.log(myThingy.staticthing); // "immutable" 

Đối tượng.đóng băng đang làm việc ở đây

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

nếu bạn muốn, bạn có thể để lại tài sản ra khỏi dụ tĩnh bằng cách bỏ nó ra khỏi đối tượng trở lại đen trên hàm constructor.

const sẽ chỉ làm cho nó trở thành tham chiếu chỉ đọc. Ngay sau khi bạn chỉ định nó, như ở đây trong một đối tượng theo nghĩa đen nó sẽ trở thành một tài sản của đối tượng được xây dựng.

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