55

なぜ定数自体を変数であるオブジェクトのプロパティとして設定できないのですか?

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を信じていますが、理由を尋ねる必要があります

4

6 に答える 6

69

定数ではできません。希望どおりに動作するが、定数を使用しない唯一の可能な方法は、書き込み不可のプロパティを定義することです。

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

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

編集:JavaScriptのオブジェクトリテラルは実際には「参照渡し」ではなく、 call-by-sharingを使用していることに注意してくれた@pstに感謝します:

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

于 2012-06-01T02:14:14.063 に答える
4

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
于 2016-08-04T16:39:08.060 に答える