为什么这里只调用最后一个对象的函数?

时间:2016-04-19 19:43:34

标签: javascript

哇。我终于想到了导致这个bug的原因,但我无法弄清楚原因。我有一个带有属性的对象(原谅大量代码转储)

    // relatives second indices in the video to events 
    // that are called when the video reaches that second
    this.PausePoints = [
        {
            sec: 10,
            name: "Point number 1",
            passed: false,
            func: (function(that) {

                this.$layer = that.GetLayerElement(10);
                this.$layer.hide();

                this.to = function () {
                    that.videlem.pause(); // pause video
                    $(window).resize(); // re-proportion stuff
                    // point the 3 mouse pointers
                    var $mptrs = this.$layer.find('.filmstrip-pointer');
                    for (var i = 0; i < $mptrs.length; ++i) {
                        (function (j) {
                            setTimeout(function () {
                                Point($mptrs.eq(j));
                            }, j * 1000);
                        })(i);
                    }
                };



                // attach click event to 3 sections
                $clickRegions = $layer.find('div.click-region');
                $clickRegions.click(function(){
                    $clickRegions.removeClass('clicked');
                    $(this).addClass('clicked');
                });

                this.away = function () {
                    this.$layer.hide();
                }

                // attach event to next button 
                $layer.find('.next-btn').click(function(){
                    this.away();
                    that.videlem.play();
                }.bind(this));

                return this;

            })(this)
        },
        {
            sec: 26,
            name: "Point number 2",
            passed: false,
            func: (function(that) {

                this.$layer = that.GetLayerElement(26);
                this.$layer.hide();

                this.to = function () {

                    // loop video between 0:26-0:31
                    this.loop = setInterval(function () {
                        that.videlem.currentTime = 26;
                        that.videlem.play();
                    }, 5000);

                    // point the 3 mouse pointers
                    var $mptrs = this.$layer.find('.filmstrip-pointer');
                    for (var i = 0; i < $mptrs.length; ++i) {
                        (function (j) {
                            setTimeout(function () {
                                Point($mptrs.eq(j));
                            }, j * 1000);
                        })(i);
                    }

                    this.$layer.show();

                }


                // separate pargraph words by spans
                this.$layer.find('p').each(function () {
                    var spanned = $(this).text().split(" ").map(function (w) { return '<span class="word">' + w + '</span>'; }).join(" ");
                    $(this).html(spanned);
                });

                // add event click event on headlines 
                var timeouts = [];
                this.$layer.find('h3').click(function () {
                    // clear any current 'showing' animations
                    timeouts.forEach(function(t){ clearTimeout(t); });
                    timeouts = [];
                    // unshow all words on the slide
                    this.$layer.find('span.word').removeClass('shown');
                    // show all words associated with the headline that was clicked
                    var $wspans = $(this).closest('.tower-layer').find('span.word');
                    for ( var i = 0; i < $wspans.length; ++i )
                    {
                        (function(j){
                            timeouts.push(setTimeout(function(){
                                $wspans.eq(j).addClass('shown');
                            },j*100));
                        })(i);
                    }
                }.bind(this));

                this.away = function () {
                    clearInterval(this.loop);
                    this.$layer.find('span.word').removeClass('shown');
                    $layer.hide();
                    that.videlem.currentTime = 31;//go to end of loop
                };

                // set action of "Next" button
                this.$layer.find('.next-btn').click(function () {
                    this.away();
                    that.videlem.play();
                }.bind(this));

                return this;

            })(this)
        },
        {
           sec: 38,
           name: "Point number 3",
           passed: false,
           func: (function(that) {

               this.$layer = that.GetLayerElement(38);
               this.$layer.hide();

               this.to = function ( ) {
                   // loop video between 0:38-0:43
                   this.loop = setInterval(function () {
                       that.videlem.currentTime = 38;
                       that.videlem.play();
                   }, 5000);

                   this.$layer.show();
               }

               this.away = function(){
                   clearInterval(this.loop);
                   this.$layer.hide();
               };

               this.$layer.find('.next-btn').click(function(){
                   that.videlem.currentTime = 43;
                   this.away();
                   that.videlem.play();
               }.bind(this));

               return this;

           })(this)
        },
        {
            sec: 47,
            name: "Point number 4",
            passed: false,
            func: (function(that){

                this.$layer = that.GetLayerElement(47);
                this.$layer.hide();

                this.to = function () 
                {
                    // loop video between 0:47-0:52
                    this.loop = setInterval(function() {
                        that.videlem.currentTime = 47;
                        that.videlem.play();
                    }, 5000);
                    // show layer
                    this.$layer.show();
                }

                this.away = function () {
                    clearInterval(this.loop);
                    this.$layer.hide();
                };

                this.$layer.find('.next-btn').click(function () {
                    that.videlem.currentTime = 52;
                    this.away();
                    that.videlem.play();
                }.bind(this));

                return this;

            })(this)
        },
        {
            sec: 57,
            name: "Point number 5",
            passed: false,
            func: (function(that){

                this.$layer = that.GetLayerElement(57);
                // hide initially
                this.$layer.hide();

                this.to = function () 
                {
                    // loop video between 0:57-1:02
                    this.loop = setInterval(function () {
                        that.videlem.currentTime = 57;
                        that.videlem.play();
                    }, 5000);

                    this.$layer.show();
                }

                this.away = function(){
                    clearInterval(this.loop);
                    $layer.hide();
                };

                this.$layer.find('.next-btn').click(function () {
                    that.videlem.currentTime = 62;
                    this.away();
                    that.videlem.play();
                }.bind(this));

                return this;

            })(this)
        }
    ];

我注意到的是,当我尝试调用任何to函数时,它总是调用数组最后一个元素中的函数。

例如,

VidHandler.PausePoints[0].func.to() 

呼叫

                this.to = function () 
                {
                    // loop video between 0:57-1:02
                    this.loop = setInterval(function () {
                        that.videlem.currentTime = 57;
                        that.videlem.play();
                    }, 5000);

                    this.$layer.show();
                }

而不是预期的

                this.to = function () {
                    that.videlem.pause(); // pause video
                    $(window).resize(); // re-proportion stuff
                    // point the 3 mouse pointers
                    var $mptrs = this.$layer.find('.filmstrip-pointer');
                    for (var i = 0; i < $mptrs.length; ++i) {
                        (function (j) {
                            setTimeout(function () {
                                Point($mptrs.eq(j));
                            }, j * 1000);
                        })(i);
                    }
                };

为什么会发生这种情况,我该如何解决?

1 个答案:

答案 0 :(得分:1)

问题是您正在尝试使用立即调用的函数表达式(IIFE)为func分配内容。那些IIFE在构造对象之前执行,这意味着this指的是其他东西。您的代码基本上可以这样分解:

this.to = function() {
  // version for "Point number 1"
};
this.to = function() {
  // version for "Point number 2"
  // notice that you're overwriting the previous one
};

// repeat for all points

var self = this;
this.PausePoints = [
  {
    name: "Point number 1",
    func: self
  },
  // repeat for all points
];    

因此,您实际执行的操作是将to值分配给具有PausePoints属性的同一对象。