哇。我终于想到了导致这个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);
}
};
为什么会发生这种情况,我该如何解决?
答案 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
属性的同一对象。