6

サイズの変更を通知できるように、 (主に学術的な理由で) 配列のlengthusingにアクセサーを設定できるようにしたいと考えています。Object.defineProperty()

私は ES6 オブジェクト監視と watch.js を認識していますが、V8/Chrome のみの場合でも、可能であれば追加のライブラリを使用せずに ES5 でこれを実行したいと考えています。

サンプル配列:

var demoArray = ['one', 'two']

悲しいかな、Chrome はそのままでは長さを設定できません。

Object.getOwnPropertyDescriptor(demoArray, 'length')
Object {value: 2, writable: true, enumerable: false, configurable: false}

そして、それは機能しません:

Object.defineProperty(demoArray, 'length', { set: function(){ console.log('length changed!')} })

で失敗する'TypeError: Cannot redefine property: length'

ご覧のとおり、そうconfigurableですfalse-したがって、失敗は理解できます。ただし、MDN によれば、可能であるはずです。

defineProperty配列のlengthプロパティを操作するにはどうすればよいですか? これは機能するはずですか?

4

5 に答える 5

2

ECMAScript 15.4.5.1によると、配列には独自の[[DefineOwnProperty]]内部メソッドがあるため、configurable: false必ずしもすぐに問題が解決するわけではありません。この方法の初期段階では、次のように述べています。

3. P が"length"の場合、

  a. Descの[[Value]]フィールドが存在しない場合、

     私。Aでデフォルトの[[DefineOwnProperty]]内部メソッド (8.12.9)を呼び出し、"length"引数として 、Desc、および Throw を渡した結果を返します。

valueしたがって、プロパティ記述子に属性がない場合、プロパティ設定操作は既定の[[DefineOwnProperty]]メソッドに委任されます。ECMAScript 15.4.5.2では、lengthプロパティに が必要なconfigurable: falseため、デフォルトのメソッドは失敗します。

setを行う場合value、デフォルトのメソッドに落ちないようにするために、setter も定義できません。そうしようとすると、Chrome (またはセクション 8.10に準拠したブラウザー) でエラーが発生します。

TypeError: Invalid property. A property cannot both have accessors and be writable or have a value

lengthしたがって、 ES5 準拠の実装では、配列にセッターを定義することは不可能のようです。

MDN の記事では、ブラウザがvalueusingの設定を誤って拒否しているように見えることに注意してくださいdefineProperty。これ通常は可能ですが、バグのためにそうでない場合もあります。

于 2013-09-05T15:10:31.753 に答える
1

「イベントリスナーを Array.length に追加すると、アプリケーションの全体的なパフォーマンスに大きな影響を与えるため、絶対に避ける必要があります」@Juno;

「配列の長さプロパティを再定義して機能させたり、特定の方法で機能させたりしないでください」 MDN;

長さに触れることはできないため、同様の動作を行うために、push メソッドを変更し、それを使用して配列に新しい値を追加することができます。

var a = ['a','b'];
a.push = function(x){
  console.log('added: ',x,', length changed: ',(this.length+1)); 
  this[this.length]=x
}
a.push('c');
于 2013-09-05T18:52:46.303 に答える