如何使用 const 关键字创建 Javascript 常量作为对象的属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10843572/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 03:12:15  来源:igfitidea点击:

How to create Javascript constants as properties of objects using const keyword?

javascriptobjectpropertiesconst

提问by danronmoon

How come constants cannot be set as properties of objects which are variables themselves?

为什么常量不能被设置为对象的属性,而这些对象本身就是变量?

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

And how come constants passed by reference suddenly become variable? EDIT: I know App won't (or rather... SHOULDN'T) be mutable; this is just an observation...

为什么通过引用传递的常量突然变成可变的?编辑:我知道 App 不会(或者更确切地说......不应该)是可变的;这只是一个观察...

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

How can a nicely organized, extensible, object-oriented, singly namespaced library containing constants be made with these limitations?

一个组织良好的、可扩展的、面向对象的、包含常量的单一命名空间的库如何在这些限制下制作?

EDIT: I believe zi42, but I just have to ask why

编辑:我相信zi42,但我只需要问为什么

回答by ziad-saab

You cannot do it with constants. The only possible way to do something that behaves like you want, but is not using constants, is to define a non-writable property:

你不能用常量来做到这一点。做一些像你想要的那样但不使用常量的事情的唯一可能的方法是定义一个不可写的属性:

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

Regarding your question as to why a constpassed to a function becomes variable, the answer is because it's passed by value and not by reference. The function is getting a new variable that has the same value as your constant.

关于为什么const传递给函数的 a 变成变量的问题,答案是因为它是通过值而不是通过引用传递的。该函数正在获取一个与常量具有相同值的新变量。

edit: thanks to @pst for noting that objects literals in javascript are not actually "passed by reference", but using call-by-sharing:

编辑:感谢@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.

尽管该术语在 Python 社区中被广泛使用,但在其他语言(如 Java 和 Visual Basic)中的相同语义通常被描述为按值调用,其中该值隐含为对对象的引用。

回答by zloctb

const person = {
    name: "Nicholas"
};

// works
person.name = "Greg";



console.log(person) //Greg 

That's why use Object.defineProperty

这就是为什么使用 Object.defineProperty

回答by p0wdr.com

There is a far simpler way to do this. I like this pattern. Simple Objects.

有一种更简单的方法可以做到这一点。我喜欢这个图案。简单的对象。

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 is doing the work here

Object.freeze 在这里完成工作

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

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

if you want you can leave the static property off the instance by leaving it off the object literal return on the constructor function.

如果您愿意,您可以通过将静态属性从构造函数上的对象字面量返回中移除,从而将静态属性从实例中移除。

const will only make it a read-only reference. As soon as you assign it, like here in a object literal it becomes a property of the constructed object.

const 只会使它成为只读引用。一旦您分配它,就像在对象文字中一样,它就成为构造对象的属性。

回答by ?? C?ng B?ng

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

We should set also configurableto be falseso that it will prevent the property from being deleted from the obj

我们还应该将可配置设置为false以防止从 obj 中删除该属性

delete obj.MY_FAKE_CONSTANT;

With configurableto be true, after the line, we don't have the MY_FAKE_CONSTANTanymore.

随着配置的,行之后,我们没有MY_FAKE_CONSTANT了。

Reference

参考

回答by Jeffrey Perron

You should not forgot than the const declaration"creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned"

您不应该忘记const 声明“创建对值的只读引用。这并不意味着它持有的值是不可变的,只是变量标识符不能重新分配”

The const keyword work in a similar way than 'let', so you can redeclare it in an other block

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

Just like @ziad-saab mantioned if you want an object property than act like a constant, you have to define it as a non-writable property.

就像@ziad-saab 规定的那样,如果您想要一个对象属性而不是一个常量,您必须将其定义为不可写属性。

if your constant is an object and is property should not change, use Object.freeze()to make the object immutable.

如果您的常量是一个对象并且属性不应更改,请使用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

回答by oscar dominguez

I thinks that you should define a constant in property making configurable:false and writable:false in Object.defineProperty, if you leave configurable:true then you can still making changes to the property

我认为您应该在 Object.defineProperty 中的属性制作中定义一个常量,使可配置:假和可写:假,如果您保留可配置:真那么您仍然可以对属性进行更改

for example: when you set configurable:true in Object.defineProperty

例如:当你在 Object.defineProperty 中设置了 configure:true 时

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

With this you are making obj.name 'constant' but after you could do

有了这个,你正在使 obj.name 'constant' 但在你可以做之后

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

But if you set configurable to false then you could never edit writable property.

但是,如果您将可配置设置为 false,那么您将永远无法编辑可写属性。

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

And for all properties you could use Object.freeze

对于所有属性,您可以使用 Object.freeze

Object.freeze(obj);

Object.freeze will iterate over enumerable properties only

Object.freeze 将仅迭代可枚举的属性