这等于requestAnimationFrame回调中的窗口

时间:2014-02-27 23:05:21

标签: javascript

我有一些使用揭示模块模式的图库代码:

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

2 个答案:

答案 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)