Jak tworzyć stałe Javascript jako właściwości obiektów za pomocą słowa kluczowego const?

Dlaczego stałe nie mogą być ustawiane jako właściwości obiektów, które same są zmiennymi?

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

I dlaczego stałe przekazywane przez odniesienie nagle stają się zmienne? EDIT: wiem, że aplikacja nie będzie (a raczej... Nie powinien) być zmienny; 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 można stworzyć ładnie zorganizowaną, rozszerzalną, zorientowaną obiektowo bibliotekę z pojedynczą przestrzenią nazw zawierającą stałe z tymi ograniczeniami?

EDIT: wierzę zi42, ale muszę zapytać dlaczego

Author: Community, 2012-06-01

5 answers

Nie można tego zrobić ze stałymi. Jedynym możliwym sposobem zrobienia czegoś, co zachowuje się tak, jak chcesz, ale nie używa stałych, jest zdefiniowanie nie-zapisywalnej właściwości:

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

Jeśli chodzi o twoje pytanie, Dlaczego const przekazywana do funkcji staje się zmienną, odpowiedź brzmi, ponieważ jest przekazywana przez wartość, a nie przez odniesienie. Funkcja otrzymuje nową zmienną, która ma taką samą wartość jak stała.

Edit : dzięki @pst za Zauważenie, że obiekty w javascript nie jest w rzeczywistości "przekazywany przez odniesienie", ale za pomocą call-by-sharing :

Chociaż termin ten jest szeroko stosowany w społeczności Pythona, identyczna semantyka w innych językach, takich jak Java i Visual Basic, jest często opisywana jako call-by-value, gdzie wartość jest sugerowana jako odniesienie do obiektu.

 38
Author: ziad-saab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-01 02:37:09
const person = {
    name: "Nicholas"
};

// works
person.name = "Greg";



console.log(person) //Greg 

Dlatego użyj obiektu.defineProperty

 4
Author: zloctb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-02 03:19:54

Jest na to znacznie prostszy sposób. 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.freeze robi tu robotę

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

Jeśli chcesz, możesz zostawić statyczną właściwość poza instancją, pozostawiając ją poza obiektem dosłownym zwrotem w funkcji konstruktora.

Const uczyni go tylko referencją tylko do odczytu. Jak tylko go przypiszesz, jak tutaj w sensie dosłownym obiekt staje się własnością konstruowanego obiektu.

 4
Author: p0wdr.com,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-15 10:10:25

Nie należy zapominać o const declaration "tworzy odniesienie tylko do odczytu do wartości. Nie oznacza to, że posiadana wartość jest niezmienna, tylko, że identyfikator zmiennej nie może być ponownie przypisany "

Słowo kluczowe const działa w podobny sposób niż 'let' , więc można je ponownie zgłosić 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

Tak jak @ziad - saab jeśli chcesz mieć właściwość obiektu niż działać jak stała, musisz zdefiniować ją jako właściwość nie do zapisania.

Jeśli twój stała jest obiektem i właściwość nie powinna się zmieniać, należy użyć obiektu .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
 2
Author: Jeffrey Perron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-04 16:39:08
var obj = {};
Object.defineProperty( obj, "MY_FAKE_CONSTANT", {
  value: "MY_FAKE_CONSTANT_VALUE",
  writable: false,
  enumerable: true,
  configurable: false // instead of true
});

Powinniśmy ustawić również konfigurowalne na fałsz Aby zapobiec usunięciu własności z obj

delete obj.MY_FAKE_CONSTANT;

Z konfigurowalnym aby być prawda, po linii nie mamy już MY_FAKE_CONSTANT.

Numer referencyjny

 2
Author: Cong Bang DO,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-09 15:58:00