简体   繁体   English

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

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

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;编辑:我知道 App 不会(或者更确切地说......不应该)是可变的; this is just an observation...这只是一个观察...

(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,但我只需要问为什么

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 const passed to a function becomes variable, the answer is because it's passed by value and not by reference.关于为什么传递给函数的const变成变量的问题,答案是因为它是按值而不是按引用传递的。 The function is getting a new variable that has the same value as your constant.该函数正在获取一个与常量具有相同值的新变量。

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)中的相同语义通常被描述为按值调用,其中该值隐含为对对象的引用。

const person = {
    name: "Nicholas"
};

// works
person.name = "Greg";



console.log(person) //Greg 

That's why use Object.defineProperty这就是为什么使用 Object.defineProperty

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. const 只会使它成为只读引用。 As soon as you assign it, like here in a object literal it becomes a property of the constructed object.一旦您分配它,就像在对象文字中一样,它就成为构造对象的属性。

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 configurable to be false so that it will prevent the property from being deleted from the obj我们还应该将可配置设置为false以防止从 obj 中删除该属性

delete obj.MY_FAKE_CONSTANT;

With configurable to be true , after the line, we don't have the MY_FAKE_CONSTANT anymore.配置true ,在该行之后,我们不再有MY_FAKE_CONSTANT了。

Reference 参考

You should not forgot that 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

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 将仅迭代可枚举的属性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM