ste*_*fan 128 javascript html5 google-chrome typeerror
当我用requestAnimationFrame
以下代码做一些原生支持的动画时:
var support = {
animationFrame: window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame
};
support.animationFrame(function() {}); //error
support.animationFrame.call(window, function() {}); //right
Run Code Online (Sandbox Code Playgroud)
直接打电话给support.animationFrame
意志......
未捕获的TypeError:非法调用
在Chrome中.为什么?
Nem*_*moy 182
在您的代码中,您将本机方法分配给自定义对象的属性.当您调用时support.animationFrame(function () {})
,它将在当前对象(即支持)的上下文中执行.要使本机requestAnimationFrame函数正常工作,必须在上下文中执行window
.
所以这里的正确用法是 support.animationFrame.call(window, function() {});
.
警报也是如此:
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
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用Function.prototype.bind(),它是ES5标准的一部分,可在所有现代浏览器中使用.
var _raf = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame;
var support = {
animationFrame: _raf ? _raf.bind(window) : null
};
Run Code Online (Sandbox Code Playgroud)
afm*_*eva 16
您还可以使用:
var obj = {
alert: alert.bind(window)
};
obj.alert('I´m an alert!!');
Run Code Online (Sandbox Code Playgroud)
Mic*_*ski 10
当您执行方法(即分配给对象的函数)时,您可以使用this
变量来引用此对象,例如:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
obj.someMethod(); // logs true
Run Code Online (Sandbox Code Playgroud)
如果将方法从一个对象分配给另一个对象,则其this
变量引用新对象,例如:
var obj = {
someProperty: true,
someMethod: function() {
console.log(this.someProperty);
}
};
var anotherObj = {
someProperty: false,
someMethod: obj.someMethod
};
anotherObj.someMethod(); // logs false
Run Code Online (Sandbox Code Playgroud)
将requestAnimationFrame
方法分配window
给另一个对象时会发生同样的事情.本机函数(例如此函数)具有内置保护,可以在其他上下文中执行它.
有一个Function.prototype.call()
函数,允许您在另一个上下文中调用函数.您只需将它(将用作上下文的对象)作为此方法的第一个参数传递.例如alert.call({})
给出TypeError: Illegal invocation
.但是,alert.call(window)
工作正常,因为现在alert
在其原始范围内执行.
如果你.call()
像这样使用你的对象:
support.animationFrame.call(window, function() {});
Run Code Online (Sandbox Code Playgroud)
它工作正常,因为它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
Run Code Online (Sandbox Code Playgroud)
唯一的缺点Function.prototype.bind()
是它是ECMAScript 5的一部分,IE <= 8不支持.幸运的是,MDN上有一个polyfill.
正如您可能已经想到的那样,您可以使用.bind()
始终requestAnimationFrame
在上下文中执行window
.您的代码可能如下所示:
var support = {
animationFrame: (window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame).bind(window)
};
Run Code Online (Sandbox Code Playgroud)
然后你可以简单地使用support.animationFrame(function() {});
.
归档时间: |
|
查看次数: |
130705 次 |
最近记录: |