51

列挙可能性は、プロパティの 3 つの属性 (書き込み可能性、列挙可能性、構成可能性) の 1 つです。私の質問は次のとおりです。

  • JavaScriptでプロパティを列挙不可にする利点は何ですか? プロパティを列挙できないようにすることでプロパティを隠していることは知っていますが、プロパティを隠すことの利点は何ですか?
  • 列挙不可能なプロパティにアクセスできますか? はいの場合、それらを列挙不可にする利点は何ですか?
  • オブジェクトの事前定義されたすべてのプロパティが列挙不可能に設定されていますか? 配列poppushプロパティが列挙できない場合などは?
4

4 に答える 4

42

for in主な利点は、またはなどのオブジェクトのプロパティを列挙するときに表示されるものを制御できることだと思いますObject.keys()

MDN は次のように説明していますObject.defineProperty: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

Objectしたがって、通常、古いブラウザでサポートされていないメソッドのポリフィルなど、メソッドを に追加したい場合は、 .prototype. しかし、それはプロパティを列挙可能にし、ループ/キーコレクションで返されるものを台無しにします(誰もが使用するわけではない...を使用せずに)。.hasOwnProperty

したがって、次のような代わりに:

Object.prototype.myMethod = function () {
    alert("Ahh");
};

Object.defineProperty列挙できないように明示的に言うために使用できます。

Object.defineProperty(Object.prototype, 'myMethod', {
    value: function () {
        alert("Ahh");
    },
    enumerable: false
});

そうすれば、たとえば を使用する場合for (var key in obj)、「myMethod」は列挙されたアイテムにはならず、 を使用することを心配する必要はありません.hasOwnProperty。これに関する主な問題は、一部のブラウザーがもちろんそれをサポートしていないことです: http://kangax.github.com/es5-compat-table/すべてのライブラリ/コードがそれを使用しているわけではないため、常に信頼できるとは限りません外部ライブラリ/コードを正しく、常に使用する。

列挙不可能なプロパティにはいつでもアクセスできますが、オブジェクトのプロパティを列挙するときに表示されないだけです。これが主なポイントです。

そして、オブジェクトのすべての「事前定義された」プロパティは列挙不可能であると私は信じています。つまり、ネイティブ プロパティのみを意味し、必ずしも継承または作成されるとは限りません。したがって、あなたの例では列挙されpopませpushArray.prototype.indexOf、そのメソッドをサポートしていない古いブラウザーでポリフィルとして作成された場合は列挙されます...もちろん、Object.defineProperty上記の例のように使用することで回避できます。もう 1 つの例は、length列挙されていないプロパティです。

一般的な例を次に示します: http://jsfiddle.net/aHJ3g/

の使用と定義Object.keysは重要です。「ループによって提供されるのと同じ順序で、指定されたオブジェクト自体の列挙可能なプロパティの配列を返しますfor-in(違いは、for-inループがプロトタイプ チェーンのプロパティも列挙することです)。」- MDN から - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

于 2013-02-20T16:20:00.773 に答える
13

もう 1 つの大きな利点は、オブジェクトのプライベート プロパティがパブリック名前空間を汚染するのを防ぐことです。

という強力なライブラリを作成して公開したとしCosmosます。ユーザーは Node インタープリターを起動し、コンストラクターを呼び出してその新しいインスタンスを作成します。

var Cosmos = require('Cosmos');
var cosmos = new Cosmos('my empire');

これで、ユーザーは入力して Enter キーを押すだけcosmosで、サポートされているパブリック API を確認できます。2 つのうちどちらをユーザーに表示しますか?

{ name: 'my empire',
  grow: [Function: grow],
  addStar: [Function: addStar],
  beautify: [Function: beautify],
  implode: [Function: implode],
  destroy: [Function: destroy] }

また

{ _age: 25000,
  _size: 35000,
  _destroyed: false,
  name: 'my empire',
  _numStars: 200,
  _init: [Function: _init],
  grow: [Function: grow],
  _grow: [Function: _grow],
  addStar: [Function: addStar],
  _checkStatus: [Function: _checkStatus],
  beautify: [Function: beautify],
  implode: [Function: implode],
  destroy: [Function: destroy] }
于 2013-07-28T07:22:44.067 に答える
0
  • プロパティを列挙不可にすることで、引き続きアクセスできます。ただし、オブジェクトにfor inループを適用すると、列挙不可能なプロパティは繰り返されません。
  • 最初のポイントを参照してください
  • 継承されたプロパティは列挙可能です(列挙可能とマークされている限り)

    var x = {a:1, b:2} // a and b are enumerable properties by default
    x.propertyIsEnumerable("toString") // returns false, because it is not marked as enumerable
    var y = Object.create(x);
    y.c = 3;
    for(p in y) console.log(p); // this loop will print c, a and b but not toString
    
于 2013-02-20T16:16:55.127 に答える