3

Scope: I have been learning prototype inheritance in java script and I tried the following code in my web browser. I found something really interesting while executing the following code.

let animal = {
  eats: true
};
let rabbit = {
  jumps: true
};
const p=Object.create(rabbit)
rabbit.__proto__ = animal
let y=new Array(2,3)
console.log(Object.getPrototypeOf(y))
var val=y.find((b)=>(b==2));
console.log(val);
console.log(Array.isArray(y))
y.__proto__=rabbit
console.log(Array.isArray(y))
console.log(Object.getPrototypeOf(y))
var ccl=y.find((b)=>(b==2)); 

Question: I have created a array and printed its prototype and then called the find method of array and check whether it's an array using Array.isArray() method. Then I have assigned the prototype of y to rabbit object.

When I checked if it is still an array, I got true, but when calling the find method I get an error and on checking the prototype there was no functions of an array.

Then on what basis does the Array.isArray() method returns true.

Output:

[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]at: ƒ at()concat: ƒ concat()constructor: ƒ Array()copyWithin: ƒ copyWithin()entries: ƒ entries()every: ƒ every()fill: ƒ fill()filter: ƒ filter()find: ƒ find()findIndex: ƒ findIndex()findLast: ƒ findLast()findLastIndex: ƒ findLastIndex()flat: ƒ flat()flatMap: ƒ flatMap()forEach: ƒ forEach()includes: ƒ includes()indexOf: ƒ indexOf()join: ƒ join()keys: ƒ keys()lastIndexOf: ƒ lastIndexOf()length: 0map: ƒ map()pop: ƒ pop()push: ƒ push()reduce: ƒ reduce()reduceRight: ƒ reduceRight()reverse: ƒ reverse()shift: ƒ shift()slice: ƒ slice()some: ƒ some()sort: ƒ sort()splice: ƒ splice()toLocaleString: ƒ toLocaleString()toString: ƒ toString()unshift: ƒ unshift()values: ƒ values()Symbol(Symbol.iterator): ƒ values()Symbol(Symbol.unscopables): {copyWithin: true, entries: true, fill: true, find: true, findIndex: true, …}[[Prototype]]: Object
2
true
true
{jumps: true}jumps: true[[Prototype]]: Objecteats: true[[Prototype]]: Objectconstructor: ƒ Object()hasOwnProperty: ƒ hasOwnProperty()isPrototypeOf: ƒ isPrototypeOf()propertyIsEnumerable: ƒ propertyIsEnumerable()toLocaleString: ƒ toLocaleString()toString: ƒ toString()valueOf: ƒ valueOf()__defineGetter__: ƒ __defineGetter__()__defineSetter__: ƒ __defineSetter__()__lookupGetter__: ƒ __lookupGetter__()__lookupSetter__: ƒ __lookupSetter__()__proto__: (...)get __proto__: ƒ __proto__()set __proto__: ƒ __proto__()
Uncaught TypeError: y.find is not a function
    at <anonymous>:17:11
aspok
  • 285
  • 3
  • 10
  • 1
    The MDN page for [`Array.isArray()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray) links to ["Determining with absolute accuracy whether or not a JavaScript object is an array"](https://web.mit.edu/jwalden/www/isArray.html). – Ouroborus May 28 '22 at 04:10
  • 2
    Duplicate of [Difference between using Array.isArray and instanceof Array](https://stackoverflow.com/q/22289727/1048572). See also [Can I create an object for which Array.isArray() returns true without using the Array constructor or array literal?](https://stackoverflow.com/q/41170131/1048572) and [Can you fake out Array.isArray() with a user-defined object?](https://stackoverflow.com/q/8672038/1048572) for why your `rabbit` is not an array. – Bergi Jun 04 '22 at 18:10

2 Answers2

3

Depends on who you ask.


The ECMAScript 2021 Language standard says:

7.2.2 IsArray ( argument )

The abstract operation IsArray takes argument argument. It performs the following steps when called:

  1. If Type(argument) is not Object, return false.
  2. If argument is an Array exotic object, return true.
  3. If argument is a Proxy exotic object, then
    a. If argument.[[ProxyHandler]] is null, throw a TypeError exception.
    b. Let target be argument.[[ProxyTarget]].
    c. Return ? IsArray(target).
  4. Return false.

(Reformatted for this platform)

It may help to know that built-in Javascript objects have a representation that is internal to the engine. This is what the above pseudo-code is referring to. Javascript doesn't have access to some of the things that the pseudo-code refers to but the engine does.


Javascript libraries, on the other hand, typically do one of several things depending on how old the library is, how robust they want to be, or what their goal is. Since they don't have access to the engine internals, these are guesses with a high probability of being correct in the real world:

  • Modern libraries defer to Array.isArray()
  • Polyfills typically use Object.prototype.toString.call(obj) === '[object Array]' (standardized by Mozilla, I believe)
  • Duck typing: Boolean(obj) && obj.length != null && typeof obj.push === 'function'
  • Constructor based: Boolean(obj) && obj.constructor === Array
  • instanceof based: obj instanceof Array

This is not an exhaustive list.

Ouroborus
  • 16,237
  • 4
  • 39
  • 62
  • So, it basically retains the information in the engine which java script don't have access to?? – hari hara sankar Jun 05 '22 at 10:57
  • @hariharasankar Yes. I believe the two main reasons are: 1) optimizing for the common use case, and 2) conveniently representing a weekly typed language using a strongly typed language. – Ouroborus Jun 06 '22 at 03:59
-2
  • isArray method takes the argument value and evaluates based on the value.
  • When let y=new Array(2,3) is executed y's prototype object is Array which is having the find method, because of which we are able to run the find method on y.
  • But when y.__proto__ = rabbit is executed the prototype object of y gets changed to rabbit, which does not have the find method and the value of y is still [2,3]
  • Because of the prototype object change we are loosing the find method implementation so we are getting error. y value is not changed because of prototype object change because of which Array.isArray(y) is returning true.
  • You can observe all this by logging y value after each step and expanding [[Prototype]] object
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 10 '22 at 09:56