原型和事件侦听器的奇怪函数行为 - JavaScript



原始模态

我想使用通用app对象。对于这个空对象,我将根据需要添加函数。问题是某些函数将需要应用程序对象中的所有其他函数。

所以,我的问题是:如何在创建时不必定义对象内部的所有函数来构造一个大对象?我想拆分代码块,以便没有一个天文数字的长.js文件。

有一个简单的原始代码示例:

var app = {
tow: function () {
return true;
},
one: function () {
return this.tow();
}
};
// app.one() => returns true

更新的模态

这是我发现有趣的事情。我正在玩prototype模态,发现了一些奇怪的东西。当我使用此模型时,我可以添加可以调用其他添加函数的函数。但是,当我创建事件侦听器时,它无法运行代码。谁能解释为什么会这样?

修改了代码,结果意外:

function modal () {}
modal.prototype.one = function () {
return this.two();
};
modal.prototype.two = function () {
return "cool";
};
modal.prototype.init = function () {
document.getElementById('go')
.addEventListener("click", this.one);
}
var app = new modal();
app.init();
// app.one() => returns true
// event listener => returns "TypeError: this.two is not a function"

JSBIN: https://jsbin.com/vureruziza/edit?js,console,output

this.one 调用时引用 addEventListener 函数,而不是你的对象。这将解决问题

modal.prototype.init = function () {
var self = this;
document.getElementById('go')
.addEventListener("click", function(){
self.one()
});
}

将单击函数与此绑定,因为该函数将需要此上下文,而不是窗口上下文。然后在 de click 处理程序中调用你的 this.one 函数。

function modal () {}
modal.prototype.one = function () {
return this.two();
};
modal.prototype.two = function () {
return "cool";
};
modal.prototype.init = function () {
document.getElementById('go')
.addEventListener("click", function(e){ 
console.log(this.one()) 
}.bind(this));

/*
The following wil also be called but your return value 
of your this.one function won't be captured. But your code will run.
.addEventListener("click", this.one.bind(this));

Try replacing it with the above and put a debugger statement in this.one 
and see that the code will actualy be ran, just not captured to output.
*/
}
var app = new modal();
app.init();
// app.one() => returns true
// event listener => returns "TypeError: this.two is not a function"
<div id="go">go</div>

使用 ES6 胖箭头函数。更新modal.prototype.init如下 -

modal.prototype.init = function () {
document.getElementById('go')
.addEventListener("click", () => this.one());
}

编辑- 如果要调试问题,只需在函数oneconsole.logthis值,如下所示 -

modal.prototype.one = function () {
console.log(this);
return this.two();
};

您很可能会看到window对象。你肯定不会看到modal对象。

最新更新