web-dev-qa-db-ja.com

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

そして、参照によって渡された定数が突然変数になるのはなぜですか?編集:私はアプリが変更可能でないことを知っています(むしろ...する必要はありません)。これは単なる観察です...

(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を信じていますが、私はただ尋ねる必要があります なぜ

39
danronmoon

定数ではできません。あなたが望むように振る舞うが定数を使用しない何かをする唯一の可能な方法は、書き込み不可能なプロパティを定義することです:

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

関数に渡されるconstが変数になる理由に関する質問については、参照ではなく値で渡されるためです。関数は、定数と同じ値を持つ新しい変数を取得しています。

edit:JavaScriptのオブジェクトリテラルは実際には「参照渡し」ではなく、 call-by-共有

この用語は、Pythonコミュニティで広く使用されていますが、JavaやVisual Basicなど、他の言語の同一のセマンティクスは、値渡しと呼ばれます。ここで、値はオブジェクトへの参照であると暗示されています。

51
ziad-saab
const person = {
    name: "Nicholas"
};

// works
person.name = "Greg";



console.log(person) //Greg 

それがObject.definePropertyを使用する理由です

7
zloctb

これを行うには、はるかに簡単な方法があります。私はこのパターンが好きです。シンプルなオブジェクト。

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は、読み取り専用の参照のみにします。ここにオブジェクトリテラルのように割り当てると、構築されたオブジェクトのプロパティになります。

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

また、configurablefalseに設定して、プロパティが削除されないようにする必要がありますobj

delete obj.MY_FAKE_CONSTANT;

configurabletrueにすると、行の後には、MY_FAKE_CONSTANTもう。

参照

5
Cong Bang DO

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
4
Jeffrey Perron

Object.definePropertyのconfigurable:falseおよびwritable:falseを作成するプロパティで定数を定義する必要があると考えています。

例: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
})

ただし、設定可能を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は列挙可能なプロパティのみを反復処理します

1
oscar dominguez