Javascript: typeof говорит «функция», но она не может быть вызвана как функция - PullRequest
0 голосов
/ 19 мая 2018

Я действительно озадачен Javascript на этот раз:

var x = Array.prototype.concat.call;
typeof x; // function
x(); // Uncaught TypeError: x is not a function

Что здесь происходит?


Если это поможет, я также заметил:

  • x([1,2],[3,4]) тоже не работает

  • toString также считает, что это функция:

    Object.prototype.toString.call(x); // "[object Function]"
    
  • Это также происходит с Array.prototype.concat.apply.

  • Когда оно используется как выражение, оно также не работает:

    (0, Array.prototype.concat.call)([1,2],[3,4]); // Same TypeError
    

Протестировано в Chrome и Node.

1 Ответ

0 голосов
/ 19 мая 2018

Ошибка вводит в заблуждение.x является функцией, но она потеряла ссылочную функцию (concat), которая выдает ошибку

Запуск в Firefox дает более описательную ошибку

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Called_on_incompatible_type

То, что она говорит, - то, что функция call не имеет ничего общего с.Таким же образом, что если вы возьмете объект, подобный этому:

const a = {
  b: 2,
  test() {
    console.log('hi', this.b);
  }
};
const c = a.test;
c();

Вы получите hi undefined, так как вы потеряли отношение функции к b.

Вы можете исправитьэто делается либо с помощью c.bind(a)(), либо c.call(a)

Функция call ведет себя аналогично.Это будет то же самое для каждой функции, и псевдокод будет выглядеть примерно так:

class Function {
  constructor(functionDefinition) {
    this.functionDefinition = functionDefinition;
  }

  call(newThis, ...args) {
    // take this.functionDefinition, and call it with `this` and `args`
  }
}

Поскольку вы извлекаете функцию вызова, она теряет объект функции,связанный с.

Вы можете исправить это, связав concat с функцией или используя вызов по вызову :-)

const a = []
const boundFn = a.concat.call.bind(a.concat)
console.log(boundFn([3], [1,2]));

// Or, you can use `call` to pass in the concat function
const callFn = a.concat.call;
console.log(callFn.call(a.concat, [4], [1,2]))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...