Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 将模块模式与闭包相结合的最佳方法_Javascript_Design Patterns_Closures - Fatal编程技术网

Javascript 将模块模式与闭包相结合的最佳方法

Javascript 将模块模式与闭包相结合的最佳方法,javascript,design-patterns,closures,Javascript,Design Patterns,Closures,我目前正在尝试实现一些常见的JS概念 在小项目中更好地理解如何使用它们 我一直在做一个简单的游戏,试图 理解并使用模块模式和闭包。 我使用的是Stoyan Stefanov的“模式”中的模块模式 书 我正在努力理解如何最好地混合模块和 关闭 我想知道我是否在组织以下代码 明智的方法?如果是这样,我的问题是:什么是最好的方式 修改代码,以便在$(function(){})中 是否可以访问update()函数 MYAPP.utilities = (function() { return {

我目前正在尝试实现一些常见的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) 绑定
$(“#按钮”)。在('click',…)
上作为 StartName初始化代码

(2) 将
update()
函数分配给一个变量,然后 从startGame函数返回此变量,因此
$(function(){})
我们可以
updatefn=MYAPP.game.startGame()然后
$(“#按钮”)。在('click',MYAPP.game.update)

(3) ??有更好的办法吗

非常感谢您的帮助


Robin

首先,要以这种方式访问
update
函数,它必须在返回的对象中公开

return {
    update: function() {
        [...]
    },
    startGame: function() {
        [...]
        this.update();
    }
}
调用
obj.method()。也就是说,调用
MYAPP.game.startGame()
this
设置为
MYAPP.game
方法调用中的
startGame
。有关此行为的更多详细信息

您还需要将
lifes
变量移动到一个公共范围,该范围可由
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();
        }
    }
})();

在这种情况下,您需要一些方法来设置
lifes
变量。另一种方法是将
lifes
变量作为返回对象的属性,并通过方法内部的
this.lifes
对其进行访问,从而使其成为公共变量

注意:如果只传递对函数对象的引用,该函数对象存储为返回对象的属性,如中所示:

$('#button').on('click', MYAPP.game.update);
单击处理程序中的
this
引用将指向
MYAPP.game
,因为传递的函数引用将直接从jQuery核心调用,而不是作为对象的成员函数调用-在这种情况下,
将指向
#按钮
元素,因为jQuery事件处理程序将
引用设置为触发处理程序的元素,如您所见

要补救,您可以使用:

或者旧的函数包装技巧:

$('#button').on('click', function() {
    MYAPP.game.update(); //called as method of an obj, sets `this` to MYAPP.game
});

当在
更新
方法中使用
关键字时,这一点很重要。

代码中存在一些问题。首先,
update()
函数在动态创建的对象外部不可见。要使它成为
游戏
对象的一部分,它必须与
开始名
处于同一级别

另外,如果您声明
var lifes=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) 

});

谢谢-这很有道理
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) 

});