Skip to content
Advertisement

why js can’t run method as a function

javascript

console.log([1, 2].map([1, 2].indexOf));

error: Uncaught TypeError: Array.prototype.indexOf called on null or undefined

but this works

console.log([1, 2].map((x) => [1, 2].indexOf(x)));

And in python.

print(list(map([1, 2].index, [1, 2])))

This works.

So why the first way failed?

Advertisement

Answer

indexOf requires a this value of an array. Passing

[1, 2].indexOf

is the same as passing Array.prototype.indexOf:

console.log(
  [1, 2].indexOf === Array.prototype.indexOf
);

A similar one:

'use strict';
class Something {
  prop = 'prop';
  method() {
    console.log(this);
  }
}
const s = new Something();
function foo(callback) {
  callback();
}
foo(s.method);

Passing it as a callback instead of invoking it normally means that the this of the [1, 2] gets lost. For similar reasons, the following doesn’t log the array:

'use strict';
// just for example, don't do this
Array.prototype.foo = function() {
  console.log(this);
}

const arr = [1, 2];
arr.map(arr.foo);

To pass a this value to .map to indicate the calling context of the callback, you need to pass another argument (though this is extremely odd):

const arr = [1, 2];
console.log(arr.map(arr.indexOf, arr));

Calling the indexOf inline instead of passing it as a callback usually makes more sense.

Advertisement