繁体   English   中英

单例模式与Javascript中的全局变量用例?

[英]Singleton pattern vs. Global variable use cases in Javascript?

背景

我正在自学编程(目前专注于JS)并且难以概念化Singleton设计模式。 https://en.wikipedia.org/wiki/Singleton_pattern )介绍说明:

“[S] ome批评单身模式[考虑将其引入]应用程序中的全局状态。” (第1段)。“

文章正文指出:“单身人士往往更喜欢全局变量,因为:他们不会用不必要的变量污染全局命名空间(或者,在具有命名空间的语言中,包含其名称空间)。”

综合考虑,这些陈述混淆了我对单身人士是什么以及什么时候应该用来取代全球变量的理解。

问题/问题

任何人都可以共享一个可以在JS中使用Singleton或Global Variable实现的示例场景,并提供每个策略何时合适的用例? 类比和隐喻以及代码是非常有用的!

命名空间

考虑像这样的index.html:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Namespace</title>
</head>

<body>
    <div id="output">&nbsp;</div>

    <script src="scriptONE.js"></script>
    <script src="scriptTWO.js"></script>

    <script>
        print();
    </script>
</body>

</html>

scriptONE.js所在的位置

var output = "ONE";

var print = function() {
    var div = document.getElementById("output");
    div.innerHTML = output;
}

并且scriptTWO.js包含

var output = "TWO";

var print = function() {
    var div = document.getElementById("output");
    div.innerHTML = output;
}

......运行这个,会发生什么? 是的,该网站将显示两个 因为这两个脚本基本上都在污染全局命名空间,因此会发生冲突。 ScriptONE的print由scriptTWO的同名函数替换。

如果我们像这样编辑scriptTWO.js,问题依然存在

var output = "TWO";

var printTWO = function() {
    var div = document.getElementById("output");
    div.innerHTML = output;
}

......因为? 对! output仍然围绕@global进行开拓。 print()被调用时, var output已被覆盖。

现在,我们可以包含我们自己的脚本(scriptTWO),而不是检查我们在某处清除的每个脚本(scriptONE)并避免它放入全局命名空间中的每个变量名称。

// obviously our countainer should not be named "print"
var myPrintDemo = {};

(function PRINTMODULE(api) {
    var output = "TWO";

    api.print = function () {
        var div = document.getElementById("output");
        div.innerHTML = output;
    }
}(myPrintDemo));

我们的index.html现在显示: ONE ,我们可以用新的myPrintDemo.print()替换print() ,使页面显示为TWO

...但为什么? 发生了什么? 我们在那里做的伏都教是什么?

我们创建了对象myPrintDemo 接下来我们'立即调用'函数PRINTMODULE。 每当遇到类似这样的事情时都会这样做(function () { ... }()); 该函数立即调用; 因此模式的名称:立即调用的函数表达式。

我们使用了这个模式并将它作为我们的对象(通过将它放入最后一对() )。 我们告诉我们的函数在内部引用它作为api 现在一切都没有api. 在它前面基本上是一个私有变量,它只在我们的PRINTMODULE函数范围内可见。 然而,我们用api. “加上”前缀的一切api. 将作为对象myPrintDemo的属性之一进行访问。

这个模块模式很方便(,伏都教)和重要的,你应该更多地检查它和某些比我更有能力的地方。 也许一本书? 我很喜欢Douglas Crockford的“Javascript The Good Parts”。 哎呀,这让我理解了scope 我实际买了它,但它也可以在这里阅读: http//bdcampbell.net/javascript/book/javascript_the_good_parts.pdf

使用http://jslint.com/学习JScript,你可以更多地依赖Crockford。

意见可能会有所不同,但为自己说话:没有什么比教我一起教我更多的东西......然后让它通过jslint!

辛格尔顿?

行。 因此,使用单个对象来包含我们所有的东西都有其优点。 它“将全局状态引入应用程序”这一点显然没有实际意义,因为JScript带有全局性。

但这个模块设计模式真的是单身吗? 罗。 我们试图将自己包含在全局命名空间中的单个对象中。 但是单身实际上需要这个特征必然是唯一的。

var Singleton = (function () {
    var instance;

    function createInstance() {
        var that = {};

        // define our module here

        return that;
    }

    // now this is the part that makes it a singleton:
    return {
        get: function () {
            if (!instance) {
                // only create an instance if there is none!
                instance = createInstance();
            }
            // always return the same object!
            return instance;
        }
    };
})();

正如您所注意到的:这是用我们的内容填充对象的一种稍微不同的方式。 我们不是首先声明Singleton一个对象然后将它提供给一个iffy(立即调用的函数表达式),而是直接将它声明为iffy的结果。

你可以使用任何一种方式。 这种差异并不是使这种模式产生更多真正的单身人士的原因。 这是JScript对Singleton的实现,因为检查是否已经存在createInstance()内部的任何实例。

(我正在使用第一种方式来显而易见地使用api.来公开事物)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM