Quando uso requestAnimationFrame
para fazer alguma animação nativa suportada com o código abaixo:
var support = {
animationFrame: window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
};
support.animationFrame(function() {}); //error
support.animationFrame.call(window, function() {}); //right
Diretamente chamando o support.animationFrame
dará ...
Tipo não detectadoErro: invocação ilegal
no Chrome. Por quê?
fonte
myObj.myAlert('this is an alert');
é ilegal. O uso correto émyObj.myAlert.call(window, 'this is an alert')
. Leia as respostas corretamente e tente entendê-las.Você também pode usar:
fonte
var realReplaceState = history.replaceState.bind(history);
.bind(localStorage)
não.bind(window)
.Quando você executa um método (ou seja, função atribuída a um objeto), dentro dele, você pode usar a
this
variável para se referir a esse objeto, por exemplo:Se você atribuir um método de um objeto para outro, sua
this
variável se refere ao novo objeto, por exemplo:O mesmo acontece quando você atribui o
requestAnimationFrame
método dewindow
a outro objeto. Funções nativas, como essa, têm proteção interna contra execução em outro contexto.Existe uma
Function.prototype.call()
função que permite chamar uma função em outro contexto. Você apenas precisa passá-lo (o objeto que será usado como contexto) como um primeiro parâmetro para esse método. Por exemplo,alert.call({})
dáTypeError: Illegal invocation
. No entanto,alert.call(window)
funciona bem, porque agoraalert
é executado em seu escopo original.Se você usar
.call()
com seu objeto assim:funciona bem, porque
requestAnimationFrame
é executado no escopo ewindow
não no seu objeto.No entanto, usar
.call()
sempre que quiser chamar esse método não é uma solução muito elegante. Em vez disso, você pode usarFunction.prototype.bind()
. Ele tem efeito semelhante ao.call()
, mas, em vez de chamar a função, cria uma nova função que sempre será chamada no contexto especificado. Por exemplo:A única desvantagem
Function.prototype.bind()
disso é que ele faz parte do ECMAScript 5, que não é suportado no IE <= 8 . Felizmente, há um polyfill no MDN .Como você provavelmente já descobriu, você pode usar
.bind()
para executar semprerequestAnimationFrame
no contexto dewindow
. Seu código pode ficar assim:Então você pode simplesmente usar
support.animationFrame(function() {});
.fonte