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

为什么不能将常量设置为本身就是变量的对象的属性?

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

通过引用传递的常量怎么突然变成变量?编辑:我知道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'

如何在这些限制的基础上构建一个组织良好,可扩展,面向对象,包含命名空间的名称空间的库?

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

danronmoon asked 2020-08-10T08:49:34Z
6个解决方案
53 votes

您不能使用常量来做到这一点。 做某种行为的唯一可能的方法就是定义一个不可写的属性:

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

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

编辑:感谢@pst指出javascript中的对象文字实际上并没有“通过引用传递”,而是使用了按共享调用:

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

ziad-saab answered 2020-08-10T08:49:54Z
7 votes
const person = {
    name: "Nicholas"
};

// works
person.name = "Greg";



console.log(person) //Greg 

这就是为什么使用Object.defineProperty

zloctb answered 2020-08-10T08:50:14Z
6 votes

有一种简单得多的方法可以做到这一点。 我喜欢这种模式。 简单对象。

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/恩-US/docs/Web/JavaScript/reference/global_objects/object/freeze]

如果需要,可以通过将静态属性保留在构造函数上的对象字面量返回值上,从而将静态属性保留在实例之外。

const只会使其成为只读引用。 一旦分配它,就像这里在对象常量中一样,它就成为已构造对象的属性。

p0wdr.com answered 2020-08-10T08:50:51Z
5 votes
var obj = {};
Object.defineProperty( obj, "MY_FAKE_CONSTANT", {
  value: "MY_FAKE_CONSTANT_VALUE",
  writable: false,
  enumerable: true,
  configurable: false // instead of true
});

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

delete obj.MY_FAKE_CONSTANT;

随着可配置为真,此行之后,我们不再拥有MY_FAKE_CONSTANT。

参考

Cong Bang DO answered 2020-08-10T08:51:20Z
4 votes

您不应忘记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
Jeffrey Perron answered 2020-08-10T08:51:54Z
1 votes

我认为您应该在Object.defineProperty中的属性中定义一个常量,使其可配置:false和writable:false,如果保留configurable:true,则仍然可以对该属性进行更改

例如:当您在Object.defineProperty中设置configurable:true时

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

这样,您正在使obj.name'constant',但之后您可以

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

oscar dominguez answered 2020-08-10T08:52:36Z
translate from https://stackoverflow.com:/questions/10843572/how-to-create-javascript-constants-as-properties-of-objects-using-const-keyword