2012-06-01 28 views
25

如何將常量設置爲變量本身的屬性?如何使用const關鍵字創建Javascript常量作爲對象的屬性?

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 

以及如何通過引用傳遞的常量突然變得可變? 編輯:我知道應用程序不會(或者不應該)是可變的;這只是一個觀察...

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

怎麼能一個很好的組織,可擴展的,面向對象,單獨的命名空間包含常數庫,這些限制進行?

編輯:我相信zi42,但我必須要問why

回答

33

你不能用常量做。唯一可能的途徑去做一些行爲就像你想要的,但不使用常量,是定義一個不可寫的屬性:

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

關於你的問題,爲什麼傳遞給函數的一個const變成可變的,答案是因爲它是通過價值而不是通過引用傳遞的。該函數正在獲取與常量具有相同值的新變量。

編輯:感謝@pst用於提的是,JavaScript中的對象實際上並沒有「按引用傳遞」,但使用call-by-sharing文字:

雖然這個詞有廣泛的應用在Python社區,相同其他語言(如Java和Visual Basic)中的語義經常被描述爲按值調用,其中值隱含爲對該對象的引用。

+0

是不是通過引用傳遞的對象? – danronmoon

+0

是的,但'const obj = {}'有點兒沒用,因爲引用是常量,但你仍然可以修改對象。 –

+4

編號對象不是*「通過引用傳遞」(這是一個模棱兩可的短語)。一個實現通常會「傳遞參考的*值*」,但重要的是JavaScript有[Call By Object Sharing semantics](http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing)。有趣的事實:* ECMAScript規範不使用術語「參考」*。 – 2012-06-01 02:20:21

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

// works 
person.name = "Greg"; 



console.log(person) //Greg 

這就是爲什麼使用Object.defineProperty

1

你不應該比const declaration忘記「創建了一個只讀的參考值。這並不意味着其持有的價值是不變的,只是可變標識符不能被重新分配」

在比‘讓’,這樣就可以在一個其它塊重新聲明它以類似的方式關鍵字const工作

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 

就像@ ziad-saab提到的,如果你想要一個對象屬性而不是一個常量,你必須將它定義爲一個不可寫屬性。

如果你的常量是一個對象,屬性不應該改變,使用Object.freeze()使對象不可變。

(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

有一種更簡單的方法來做到這一點。我喜歡這種模式。簡單的對象。

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" 

Object。如果你願意,你可以把它置放在關閉的構造函數的對象字面返鄉離場靜態屬性關閉實例凍結在這裏

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

做的工作。

const只會使其成爲只讀引用。只要你分配它,就像這裏的一個對象文字一樣,它就成爲了構造對象的一個​​屬性。

相關問題