Подтвердить что ты не робот

Как создать константы Javascript в качестве свойств объектов с использованием ключевого слова 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

И как же константы, пройденные по ссылке, внезапно становятся переменными? EDIT: Я знаю, что приложение не будет (или скорее... НЕ ДОЛЖНО) быть изменчивым; это просто наблюдение...

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

Как можно сделать с этими ограничениями красиво организованную, расширяемую, объектно-ориентированную библиотеку с одним пространством имен, содержащую константы?

EDIT: я считаю, zi42, но мне просто нужно спросить why

4b9b3361

Ответ 1

Вы не можете сделать это с помощью констант. Единственный возможный способ сделать что-то, что ведет себя так, как вы хотите, но не использует константы, - это определить свойство, недоступное для записи:

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

Что касается вашего вопроса о том, почему a const, переданный функции, становится переменной, ответ заключается в том, что он передается по значению, а не по ссылке. Функция получает новую переменную, которая имеет то же значение, что и ваша константа.

edit: благодаря @pst для обозначения того, что литералы объектов в javascript фактически не передаются по ссылке, но используя call -по обмен:

Хотя этот термин широко распространен в сообществе Python, идентичная семантика на других языках, таких как Java и Visual Basic, часто описывается как вызов по значению, где значение подразумевается как ссылка на объект.

Ответ 2

const person = {
    name: "Nicholas"
};

// works
person.name = "Greg";



console.log(person) //Greg 

Чтобы использовать Object.defineProperty

Ответ 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.freeze выполняет работу здесь

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

если вы хотите, вы можете оставить статическое свойство вне экземпляра, оставив его без возврата объекта объекта в конструктор.

const будет делать это только для чтения. Как только вы его назначаете, как здесь, в объектном литерале, оно становится свойством построенного объекта.

Ответ 4

Вы не должны забывать, что объявление const "создает ссылку только на чтение для значения. Это не значит, что значение, которое оно имеет, неизменяемый, просто, чтобы идентификатор переменной не мог быть переназначен"

Ключевое слово const работает так же, как "let", поэтому вы можете его повторно добавить в другой блок

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