javascript - 将模块模式与闭包相结合的最佳方式

标签 javascript design-patterns closures

我目前正在尝试实现一些常见的 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)范围,该范围可通过 startGameupdate 方法访问,这正是关闭的目的是什么:

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();
        }
    }
})();

Fiddle

在这种情况下,当您想要更改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/

相关文章:

c# - 如何合并两个asp.net mvc网站

javascript - 确保脚本可用性的模式或技术?

Javascript 对象/闭包

javascript - 从它调用的函数中中止外部函数

javascript - Ember Controller 计算属性(对象类型)更新不起作用

javascript - Google Cloud Functions 以 : timeout when using Axios 结束

c++ - 是否有用于封装线程行为的通用设计模式或面向对象的方法?

javascript - for 循环内的闭包 - 以循环变量作为参数的回调

javascript - JQuery - 如何发送表单并调用 anchor ?

javascript - 单击按钮时不显示对话框