10

It looks like Arrays created with Object.create walk like Arrays and quack like Arrays, but are still not real arrays. At least with v8 / node.js.

> a = []
[]
> b = Object.create(Array.prototype)
{}
> a.constructor
[Function: Array]
> b.constructor
[Function: Array]
> a.__proto__
[]
> b.__proto__
[]
> a instanceof Array
true
> b instanceof Array
true
> Object.prototype.toString.call(a)
'[object Array]'
> Object.prototype.toString.call(b)
'[object Object]'

Can some Javascript guru explain why it is so, and how to make it so that my newly created array is indistinguishable from a real array?

My goal here is to clone data structures, including Arrays which may have custom properties attached. I could, of course, manually attach properties to a newly-created Array using Object.defineProperty, but is there a way to do so using Object.create?

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Philippe Plantier
  • 7,964
  • 3
  • 27
  • 40
  • They're rather indistinguishable for your goal. How to make fully indistingushable -- use `b = []`; – kirilloid Jan 26 '12 at 09:55
  • @kirilloid - that might be a valid approach for some situations but in situations where say a factory function internally does the plumbing based on a prototypeParam, your suggestion is not an option. eg. in the creation of a monoid, start with: var monad = Object.create(prototypeParam); Here, it would be convenient if prototypeParam could be Array.prototype – arcseldon Oct 12 '14 at 11:52

2 Answers2

5

The short answer is no. This article explains it all in some detail.

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Tim Down
  • 318,141
  • 75
  • 454
  • 536
  • See http://www.bennadel.com/blog/2292-Extending-JavaScript-Arrays-While-Keeping-Native-Bracket-Notation-Functionality.htm for a workaround. – Gili Jan 18 '13 at 18:45
3

No, you cannot. Object.create is all about prototypes, but both [] and Object.create(Array.prototype) inherit from the same prototype object.

What you call "desired Object.prototype.toString behaviour" is the internal [[Class]] of the object, which is impossible to set up with Object.create. Creating "true arrays" (with an Array class and special array behaviour - indexed properties, .length) is only possible by using array literals or calling the Array constructor.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375