2012-06-01 12 views
25

Dlaczego nie można ustawić stałych jako właściwości samych obiektów będących zmiennymi?Jak utworzyć stałe JavaScript jako właściwości obiektów używając słowa kluczowego 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 

A jak stały stały się przez odniesienie stałe nagle stają się zmienne? EDYCJA: Wiem, że aplikacja nie będzie (lub raczej ... NIE POWINIEN) być zmienna; jest to tylko obserwacja ...

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

Jak ładnie zorganizowane, rozszerzalny, zorientowanym obiektowo, pojedynczo przestrzeni nazw biblioteki zawierającej stałe być wykonane z tych ograniczeń?

EDIT: Wierzę zi42, ale po prostu trzeba poprosić why

Odpowiedz

33

nie można zrobić ze stałymi. Jedynym możliwym sposobem, aby zrobić coś, co zachowuje się jak chcesz, ale nie używa stałych, jest zdefiniowanie właściwości bez zapisu:

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

dotycząceTwojego pytanie, dlaczego const przekazywane do funkcji staje się zmienna, odpowiedź brzmi, ponieważ jest przekazywana przez wartość, a nie przez odniesienie. Funkcja otrzymuje nową zmienną, która ma taką samą wartość jak twoja stała.

edit: dzięki @pst zauważyć, że dla obiektów literały w javascript w rzeczywistości nie są „przekazywane przez referencję”, ale przy użyciu call-by-sharing:

Chociaż termin ten jest szeroko wykorzystywany w środowisku Pythona, identyczne semantyka w innych językach, takich jak Java i Visual Basic, jest często opisywana jako call-by-value, gdzie wartość jest domniemana jako odniesienie do obiektu.

+0

Czy obiekty nie są przekazywane przez odniesienie? – danronmoon

+0

Tak, ale 'const obj = {}' jest trochę bezużyteczne, ponieważ referencja będzie stała, ale nadal możesz modyfikować obiekt. –

+4

Nr Obiekty są * nie * "przekazywane przez odniesienie" (w najlepszym przypadku jest to dwuznaczne wyrażenie). Implementacja będzie na ogół "przekazywać przez * wartość * odniesienia", ale ważne jest to, że JavaScript ma semantykę "Dzielenie się obiektami" (http://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_sharing). Ciekawostka: * specyfikacja ECMAScript nie używa terminu "referencja" *. –

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

// works 
person.name = "Greg"; 



console.log(person) //Greg 

Dlatego używać Object.defineProperty

1

Nie należy zapomniał niż const declaration „tworzy odwołanie do wartości tylko do odczytu. To nie znaczy, że posiada wartość jest niezmienna, tylko że zmienna identyfikator nie może być przeniesiony”

const praca kluczowe w podobny sposób niż«daj», więc można redeclare go w innym bloku

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 

Podobnie jak w przypadku @ ziad-saab mantioned, jeśli chcesz mieć właściwość obiektu niż działać jak stała, musisz zdefiniować ją jako własność nieprzenośną.

jeśli twoja stała jest obiektem i własność nie powinna się zmieniać, użyj Object.freeze(), aby obiekt stał się niezmienny.

(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

Istnieje znacznie prostszy sposób na zrobienie tego. Podoba mi się ten wzór. Proste obiekty.

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" 

Obiekt.zamrożenie robi pracę tutaj

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

jeśli chcesz, możesz zostawić właściwości statycznej off instancji, pozostawiając go z obiektu dosłownego zwrot funkcji konstruktora.

const spowoduje, że będzie to tylko odwołanie do odczytu. Jak tylko ją przypiszesz, tak jak tutaj, w literale obiektowym staje się ona własnością konstruowanego obiektu.

Powiązane problemy