javascriptarraysgoogle-chromeecmascript-5defineproperty

JavaScript: use defineProperty accessor on an array's .length?


I would like (mainly for academic reasons) to be able to set an accessor on an array's length using Object.defineProperty(), so than I can notify for size changes.

I am aware of ES6 object observe, and watch.js, but I would like to attempt to do this in ES5 without extra libraries if possible, even if this is only for V8/Chrome.

A sample array:

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

Alas Chrome, out of the box, makes length not configurable:

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

And it doesn't work:

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

Fails with 'TypeError: Cannot redefine property: length'

As you can see, configurable is false - so the failure is understandable. However according to MDN it should be possible.

How can I get defineProperty working on an array's length property? Should this work?


Solution

  • Since reading a little more about this, Kangax's excellent article dedicated to the topic of subclassing Array covers a a variety of techniques. One technique, called Array prototype injection is used to subclass Array in popular libraries like Ractive.js. It relies on the non-spec, but popular __proto__ being exposed, but does allow 'accessors' on length.