Вопрос по javascript – Как создать константы Javascript как свойства объектов, используя ключевое слово const?

32

Почему константы не могут быть установлены как свойства объектов, которые сами являются переменными?

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, но я просто должен спроситьЗачем

Ваш Ответ

6   ответов
40

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

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

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

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

Although this term has widespread usage in the Python community, identical semantics in other languages such as Java and Visual Basic are often described as call-by-value, where the value is implied to be a reference to the object.

Однако мой ответ остается в силе, потому что вы не сможете изменить это недоступное для записи свойство
Да, ноconst obj = {} это бесполезно, потому что ссылка будет постоянной, но вы все равно можете изменить объект.
Разве объекты не переданы по ссылке? danronmoon
@ pst & # x2014; термин "ссылка" Вероятнее всегоis Используется:reference type является спецификационным артефактом, объясняющим (среди прочего), как работает присвоение значений. Есть даже оператор «вызовам функций разрешено возвращать ссылки».
№ объектыnot & quot; передано по ссылке & quot; (в лучшем случае это двусмысленная фраза). Реализация будет обычно проходить мимоvalue ссылки & quot; но важно то, что JavaScript имеетCall By Object Sharing semantics, Интересный факт:the ECMAScript specification does not use the term "reference".
1

что вы должны определить константу в свойстве, чтобы сделать настраиваемое: ложное и доступное для записи: ложное в Object.defineProperty, если вы оставите настраиваемое: истинное, то вы все равно можете вносить изменения в свойство

например: когда вы устанавливаете configurable: true в Object.defineProperty

cosnt obj = {name: 'some name'};
Object.defineProperty(obj, 'name', {
  enumerable: true,
  configurable: true,
  writable: false
});

С этим вы делаете obj.name «постоянным» но после того, как вы могли сделать

Object.defineProperty(obj, 'name', {
  enumerable: true,
  configurable: true,
  writable: true // <-- you can set to true because configurable is true
})

Но если вы установите для configurable значение false, вы никогда не сможете редактировать свойство записи.

Object.defineProperty(obj, 'name', {
  enumerable: true,
  configurable: false, // <-- with this you never could edit writable property
  writable: false
})

И для всех свойств вы можете использовать Object.freeze

Object.freeze(obj);

Object.freeze будет перебирать только перечисляемые свойства

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

// works
person.name = "Greg";



console.log(person) //Greg 

2

декларация const & quot; создает доступную только для чтения ссылку на значение. Это не означает, что значение, которое оно содержит, является неизменным, просто то, что идентификатор переменной не может быть переназначен & quot;

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

const MyConst = 5;
console.log('global MyConst =', MyConst); //global MyConst = 5
if(true){
  const MyC,onst = 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
4

шаблон. Простые объекты.

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
var obj = {};
Object.defineProperty( obj, "MY_FAKE_CONSTANT", {
  value: "MY_FAKE_CONSTANT_VALUE",
  writable: false,
  enumerable: true,
  configurable: false // instead of true
});

Мы должны установить такжеconfigurable бытьfalse так что это предотвратит удаление свойства из объекта

delete obj.MY_FAKE_CONSTANT;

Сconfigurable бытьtrueпосле строки у нас нетMY_FAKE_CONSTANT больше.

Ссылка

Похожие вопросы