"Uncaught TypeError: незаконный вызов" в Chrome


когда я использую requestAnimationFrame чтобы сделать некоторые собственные поддерживаемые анимации с ниже кода:

var support = {
    animationFrame: window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame
};

support.animationFrame(function() {}); //error

support.animationFrame.call(window, function() {}); //right

непосредственно вызова support.animationFrame дадут...

Uncaught TypeError: незаконный вызов

В Chrome. Зачем?

4 115

4 ответа:

в коде вы присваиваете собственный метод свойству пользовательского объекта. Когда вы звоните support.animationFrame(function () {}), он выполняется в контексте текущего объекта (т. е. поддержка). Для собственной функции метод requestAnimationFrame, чтобы работать должным образом, она должна быть выполнена в контексте window.

так что правильное использование здесь support.animationFrame.call(window, function() {});.

то же самое происходит и с alert:

var myObj = {
  myAlert : alert //copying native alert to an object
};

myObj.myAlert('this is an alert'); //is illegal
myObj.myAlert.call(window, 'this is an alert'); // executing in context of window 

другой вариант-использовать

вы также можете использовать:

var obj = {
    alert: alert.bind(window)
};
obj.alert('I´m an alert!!');

когда вы выполняете метод (т. е. функцию, назначенную объекту), внутри него вы можете использовать this переменная для ссылки на этот объект, например:

var obj = {
  someProperty: true,
  someMethod: function() {
    console.log(this.someProperty);
  }
};
obj.someMethod(); // logs true

если вы назначаете метод от одного объекта к другому, его this переменная ссылается на новый объект, например:

var obj = {
  someProperty: true,
  someMethod: function() {
    console.log(this.someProperty);
  }
};

var anotherObj = {
  someProperty: false,
  someMethod: obj.someMethod
};

anotherObj.someMethod(); // logs false

то же самое происходит, когда вы назначаете requestAnimationFrame метод window на другой объект. Собственные функции, такие как это, имеет встроенную защиту от выполнения его в другом контексте.

есть Function.prototype.call() функция, которая позволяет вызвать функцию в другом контексте. Вы просто должны передать его (объект, который будет использоваться в качестве контекста) в качестве первого параметра для этого метода. Например alert.call({}) дает TypeError: Illegal invocation. Однако,alert.call(window) отлично работает, потому что теперь alert выполняется в исходном объеме.

если вы используете .call() С вашим объектом, как что:

support.animationFrame.call(window, function() {});

он отлично работает, потому что requestAnimationFrame выполняется в области window вместо вашего объекта.

, используя .call() каждый раз, когда вы хотите вызвать этот метод, не очень элегантное решение. Вместо этого, вы можете использовать Function.prototype.bind(). Он имеет аналогичный эффект .call(), но вместо вызова функции, он создает новую функцию, которая всегда будет называться в определенном контексте. Для пример:

window.someProperty = true;
var obj = {
  someProperty: false,
  someMethod: function() {
    console.log(this.someProperty);
  }
};

var someMethodInWindowContext = obj.someMethod.bind(window);
someMethodInWindowContext(); // logs true

единственный недостаток Function.prototype.bind() заключается в том, что он является частью спецификации ECMAScript 5, который не поддерживается в IE . К счастью, есть полифилл на MDN.

как вы, наверное, уже поняли, вы можете использовать .bind() всегда выполняется requestAnimationFrame в контексте window. Ваш код может выглядеть так:

var support = {
    animationFrame: (window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        window.oRequestAnimationFrame).bind(window)
};

затем вы можете просто использовать support.animationFrame(function() {});.

была эта ошибка, когда у меня было VPN-соединение, отключил VPN и решил проблему.