1

Is it possible for a JS value to be an array and a function?

const isArrayAndFunc = v => {
  return Array.isArray(v) && typeof v === 'function';
}

could isArrayAndFunc ever return true for a value in JS?

I don't think it is, but just checking.

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817

2 Answers2

1

Might be considered cheating, but it would be possible to overwrite Array.isArray to implement your own logic:

Array.isArray = () => true;
const isArrayAndFunc = v => {
  return Array.isArray(v) && typeof v === 'function';
};

console.log(isArrayAndFunc(() => 'foo'));

Internally, Array.isArray, in ES5, checks:

If the value of the [[Class]] internal property of arg is "Array", then return true.

This is an internal property, which can't be modified:

This specification defines no ECMAScript language operators or built-in functions that permit a program to modify an object’s [[Class]] or [[Prototype]] internal properties or to change the value of [[Extensible]] from false to true. Implementation specific extensions that modify [[Class]], [[Prototype]] or [[Extensible]] must not violate the invariants defined in the preceding paragraph.

In ES6:

  1. If argument is an Array exotic object, return true.
  2. If argument is a Proxy exotic object, then

    a. If the value of the [[ProxyHandler]] internal slot of argument is null, throw a TypeError exception.

    b. Let target be the value of the [[ProxyTarget]] internal slot of argument.

    c. Return IsArray(target).

For 2., there doesn't look to be any way to turn any object (or function) into an "Array exotic object". setPrototypeOf can be used to set the internal prototype of the function, but it still won't actually be an "Array exotic object".

'use strict';
const fn = () => 'foo';
Object.setPrototypeOf(fn, Array);

const isArrayAndFunc = v => {
  return Array.isArray(v) && typeof v === 'function';
};
console.log(isArrayAndFunc(fn));

For 3, if the object being examined is a Proxy, then its typeof will be an object, not a function.

So unless you overwrite Array.isArray (or, overwrite/shadow Array itself), I don't think isArrayAndFunc could ever return true.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • `Is it possible for a JS value to be an array and a function?` The question has nothing to do with your answer. Changing the function doesn't change the value – baao Jul 14 '19 at 23:21
  • 1
    The question asks `could isArrayAndFunc ever return true for a value in JS?`, so I wrote my answer trying to describe how such a thing could (or couldn't) be possible. There are a few things one might *think* one might be able to do to the function to get the `isArrayAndFunc` to return `true`, but I don't think any of them pan out. Sure seems on-topic to me, given the question – CertainPerformance Jul 14 '19 at 23:24
-1

Technically, yes... but only if someone were to override the built-in Array.isArray() method. For example:

Array.isArray = () => true;
console.log( Array.isArray( 'foo' ) );  // true
console.log( Array.isArray( []    ) );  // true
console.log( Array.isArray( ()=>1 ) );  // true

const isArrayAndFunc = v => {
  return Array.isArray(v) && typeof v === 'function';
}
console.log( isArrayAndFunc( ()=>1 ) );  // true

So, yeah, it could... but unlikely?

Jordan Kasper
  • 13,153
  • 3
  • 36
  • 55