我目前正在尝试实现一些常见的 JS 概念 在小项目中更好地了解如何使用它们。
我一直在做一个简单的游戏,试图 理解和使用模块模式和闭包。 我正在使用 Stoyan Stefanov 的“模式”中的模块模式 书。
我正在努力理解如何最好地混合模块和 关闭。
我想知道我是否将以下代码组织在
明智的方式?如果是这样,我的问题是:最好的方法是什么
修改代码,以便在 $(function(){})
我有
访问 update()
函数?
MYAPP.utilities = (function() {
return {
fn1: function(lives) {
//do stuff
}
}
})();
MYAPP.game = (function() {
//dependencies
utils = MYAPP.utilities
return {
startGame: function() {
//initialisation code
//game state, stored in closure
var lives = 3;
var victoryPoints = 0;
function update(){
utils.fn1(lives);
//do other stuff
}
}
}
})();
$(function(){
MYAPP.game.startGame();
//Want to do this, but it won't work
//because I don't have access to update
$('#button').on('click',MYAPP.game.update)
});
我想出了几个可行的选项,但是 我想知道他们是否是好的做法,什么是最好的 选项是。
选项:
(1) 绑定(bind) $('#button').on('click', ...)
作为
startGame 初始化代码。
(2) 将update()
函数赋给一个变量,然后
从 startGame 函数返回这个变量,所以在
$(function(){})
我们可以
updatefn = MYAPP.game.startGame();
然后
$('#button').on('click',MYAPP.game.update)
(3)?有没有更好的办法?
非常感谢您的帮助,
罗宾
最佳答案
首先,要以这种方式访问 update
函数,它必须在返回的对象中公开。
return {
update: function() {
[...]
},
startGame: function() {
[...]
this.update();
}
}
调用 obj.method()
会自动将此 method
调用中的 this
引用设置为 obj
。也就是说,调用 MYAPP.game.startGame()
会将 this
设置为 MYAPP.game
在此 startGame
方法调用中.有关此行为的更多详细信息 here .
您还需要将 lives
变量移动到一个公共(public)范围,该范围可通过 startGame
和 update
方法访问,这正是关闭的目的是什么:
MYAPP.game = (function() {
[...]
var lives; //private/privileged var inside the closure, only accessible by
//the returned object's function properties
return {
update: function() {
utils.fn1(lives);
},
startGame: function() {
[...]
lives = 3; //sets the closure scope's lives variable
[...]
this.update();
}
}
})();
在这种情况下,当您想要更改lives
变量时,您需要一些方法来设置它。另一种方法是通过使 lives
变量成为返回对象的属性并通过方法内部的 this.lives
访问它来公开变量。
注意:如果您只是传递对存储为返回对象属性的函数对象的引用,如下所示:
$('#button').on('click', MYAPP.game.update);
点击处理程序中的this
引用将不指向MYAPP.game
,因为传递的函数引用将被直接调用来自 jQuery 核心而不是对象的成员函数调用 - 在这种情况下,this
将指向 #button
元素,因为 jQuery 事件处理程序设置 this
对触发处理程序的元素的引用,如您所见 here .
要补救,您可以使用 Function.bind()
:
$('#button').on('click', MYAPP.game.update.bind(MYAPP.game));
或者旧的函数包装技巧:
$('#button').on('click', function() {
MYAPP.game.update(); //called as method of an obj, sets `this` to MYAPP.game
});
当在 update
方法中使用 this
关键字时,这一点很重要。
关于javascript - 将模块模式与闭包相结合的最佳方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16260596/