我有一些使用揭示模块模式的图库代码:
window.jdiGallery = (function () { //Structure from http://code.tutsplus.com/tutorials/build-your-first-javascript-library--net-26796
var instance = null;
function Gallery (nodeList, options) {
this.settings = this.extend({
'transitionSpeed': 100, //in ms
'slideSpeed': 5000
}, options);
this.requestAnimationId; //We need this handle for canceling the RAF
this.start = null; //To help determine how far we are between transitions
for(var i = 0; i < nodeList.length; i++ )
this.instances[i] = this.init(nodeList[i]);
}
Gallery.prototype.init = function(el){
var slideEls = el.querySelectorAll('* > .nd-slide');
var slides = [];
//this is equal to the Gallery instance
for(var i = 0; i < slideEls.length - 1; i++)
slides.push(new Slide(slideEls[i], i, this.settings["inTransition"], this.settings["outTransition"]));
}
Gallery.prototype.moveToNext = function(timestamp){
var progress;
if (this.start === null) //this is equal to window
this.start = timestamp;
progress = timestamp - this.start;
if (progress > 5000) {
console.log('moving to next');
this.start = null;
requestAnimationFrame(this.moveToNext);
}
}
return {
create: function (selector, options) {
//creation code omitted for brevity
instance = new Gallery(els, options);
this.requestId = window.requestAnimationFrame(instance.moveToNext);
},
调用create
时,最终会调用Gallery.init()
。在该函数中,this
等于Gallery
的实例。
然后我将Gallery.moveToNext()
作为回调传递给我的requestFrameAnimation
。当我们进入moveToNext
时,this
的值为window
。为什么它没有像我预期的那样引用Gallery
?
答案 0 :(得分:3)
是的,这是JavaScript中的常见问题。 JavaScript中的this
绑定依赖于如何调用函数。
一般规则是(针对浏览器):
如果从裸标识符调用函数,则this
设置为window
> var foo = function() { console.log(this); };
> foo();
Window
如果直接从对象调用函数,则this
设置为对象
> var bar = {
> bar: function() { console.log(this); }
> };
> bar.foo();
Object
如果使用.call()
或.apply()
调用函数,则this
设置为作为第一个参数传入的内容
在这种情况下,requestAnimationFrame
仅对moveToNext
函数本身有引用,而不是对其上下文的引用。一种解决方案是使用Function.prototype.bind
:
requestAnimationFrame(this.moveToNext.bind(this));
此外,您可以在Gallery.prototype.init
this.moveToNextBound = this.moveToNext.bind(this);
您也可以使用匿名函数,但要这样做,您需要将this
重新绑定到另一个变量。
var self = this;
requestAnimationFrame(function() { self.moveToNext.apply(arguments); });
答案 1 :(得分:1)
this.moveToNext
传递裸函数,没有上下文。您从this
获取它的事实没有任何区别。
使用this.moveToNext.bind(this)