我目前正在尝试实现一些常见的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)绑定$('#button').on('click', ...)
作为一部分
startGame初始化代码。
(2)将update()
函数分配给变量,和
从startGame函数返回此变量,所以在
我们可以$(function(){})
updatefn = MYAPP.game.startGame();
然后
$('#button').on('click',MYAPP.game.update)
(3)?还有更好的方法吗?
非常感谢您的帮助,
罗宾
答案 0 :(得分:4)
首先,要以这种方式访问update
函数,它必须在返回的对象中公开。
return {
update: function() {
[...]
},
startGame: function() {
[...]
this.update();
}
}
呼叫obj.method()
会自动将此this
来电中的method
引用设置为obj
。也就是说,在此MYAPP.game.startGame()
方法调用中调用this
将MYAPP.game
设置为startGame
。有关此行为的更多详细信息here。
您还希望将lives
变量移动到可由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
引用将不指向this
,因为已传递的函数引用将直接从jQuery核心调用而不是作为object的成员函数调用 - 在这种情况下,#button
将指向this
元素,因为jQuery事件处理程序将$('#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
});
3}}
要解决此问题,您可以使用here:
this
或旧的函数包装技巧:
update
在{{1}}方法中使用{{1}}关键字时,这很重要。
答案 1 :(得分:1)
您的代码中存在一些问题。首先,update()
函数在您即时创建的对象外部不可见。要使其成为game
对象的一部分,它必须与startGame
处于同一级别。
此外,如果您声明var lives = 3
,它将是一个局部变量,并且在startGame()
函数以及victoryPoints
之外将不可见。这两个变量必须以某种方式可见(通过闭包或作为对象字段)。
最后,将MYAPP.game.update
作为事件侦听器附加将仅附加该函数,从而阻止您使用所有其他对象方法/函数。根据您的目的,您可能更愿意传递function() { MYAPP.game.update() }
之类的闭包。
您的代码应该类似于:
MYAPP.utilities = (function() {
return {
fn1: function(lives) {
console.log(lives);
}
}
})();
MYAPP.game = (function() {
//dependencies
utils = MYAPP.utilities
var lives;
var victoryPoints;
return {
startGame: function() {
//initialisation code
//game state, stored in closure
lives = 3;
victoryPoints = 0;
},
update: function() {
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)
});
(的 DEMO on jsfiddle 强>)