Javascript Module Pattern 和 new 关键字

Javascript Module Pattern and the new keyword

本文关键字:new 关键字 Pattern Module Javascript      更新时间:2023-09-26

我了解了模块模式的基础知识及其使用闭包来允许私有成员,但我无法完全接受为什么下面的代码会这样做:

var Calculator = function() {
    var priv = 0;
    return {
        changePriv: function() { priv++;},
        printPriv: function() { console.log(priv);}
    }
}
var myCalc = Calculator();
myCalc.printPriv();
myCalc.changePriv();
myCalc.printPriv();
var myOtherCalc = Calculator();
myCalc.printPriv();

控制台输出为

0
1
1

因此,此处有意省略new关键字,第一个调用集myCalc Calculator 对象。它以 priv 值 0 开始,递增,然后打印出新的priv值 1。

但是 a)为什么下一次调用 Calculator() 最终返回对 SAME 对象的引用(如第二个"1"所示)?我知道我可以在这里使用new并避免这种情况,但不明白为什么我必须这样做。这个函数不是使用对象文字语法本质上创建一个新对象然后返回它吗?b) 既然它似乎确实使用相同的函数堆栈空间(这甚至是在 JS 中思考它的正确方法吗?),为什么在返回对同一对象的引用之前,它不在过程中将priv变量清零?

编辑:纠正了草率/愚蠢的错误(感谢scessor),即使不使用new关键字,它现在也会输出一个新的/不同的计算器对象。所以这清除了 a) 和 b)。我由此产生的问题是"在调用模块模式构造函数时,我是否使用 new 是否重要。答案是,我想没关系(?(约瑟夫:见 http://jsfiddle.net/MvMvy/5/...无论哪种方式,实例运算符都不适用于模块模式。

您不输出其他计算器myOtherCalc:如果要比较它们,请将第三个myCalc.printPriv();替换为:

myOtherCalc.printPriv();

然后输出为:

0
1
0
在这种情况下,

您不需要使用 new

通常,如果您使用 new ,您希望得到的是您调用的构造函数的实例。在您的情况下,它不会,因为您手动返回了一个对象。这是没有意义的,并且会导致以后混淆用法的问题。很快,您可能会"实例测试"您的对象,并且会遇到这种"不匹配"。

而且你的代码中有一个错别字:

var myCalc = Calculator();       //create calculator
myCalc.printPriv();              //"myCalc" private is 0
myCalc.changePriv();             //increment
myCalc.printPriv();              //"myCalc" private is 1
var myOtherCalc = Calculator();  //another calculator
myCalc.printPriv();              ///but you printed "myCalc" again

与"新"运算符无关...在这里,您可以获得有关原型/构造函数的良好解释主题:http://en.wikibooks.org/wiki/JavaScript/Access_Control

然而,这是一个无意义的示例,你可以这样做,所以你只能通过getter和setter方法访问priv:

function Calculator2() {
var priv = 0;
this.public = 0;
this.getPriv = function(){
    return  priv;
}
this.setPriv = function(val){
    priv = val;
}
}
Calculator2.prototype.changePriv = function(){
this.setPriv(this.getPriv()+1);
}
Calculator2.prototype.printPriv = function(){
    console.log("priv = " + this.getPriv());
}
Calculator2.prototype.changePublic = function(){
    this.public++;
}
Calculator2.prototype.printPublic = function(){
    console.log(this.public);
}

在这种情况下,var priv 始终可以通过 getter 和 setter 方法访问,

在下一个示例中,您有一个私有 var className 和另一个公共 var __className:

<div id = "outputDiv" style="width:600px;height:400px;border:solid 1px #000"></div>
<script type="text/javascript">
    //<![CDATA[

//脚本: var SomeClass = function(className) {

    var __className__ = className;
    this.__className__ = "'"public default className'"";
    var someString = new String("");
    this.setScopeText = function() { // void
        someString = "A new instance of '"private [__classname__] : " +
        __className__ + "'"" +
        " has been created. Refering to [__className__]<br />" +
        "A new instance of " +
        this.__className__ +
        " has been created. Refering to [this.__className__]";
        return someString;
    };
    this.getScopeText= function (){
        return someString;
    }
    this.setOutput = function(elementId, someString){
        var outputPane = this.getSomePane(elementId);
        outputPane.innerHTML += "<p>" + someString + "</p>";
    }
    this.getSomePane = function(elementId){
        var outputP = document.getElementById(elementId);
        return outputP;
    }
}
SomeClass.prototype.changeClassNameVariable = function( str ){
    this.__className__  = str;
}

结束声明。

//测试:

var sc = new SomeClass("foo");
sc.setOutput("outputDiv",sc.__className__);
sc.setOutput("outputDiv",sc.setScopeText());
sc.setOutput("outputDiv",sc.getSomePane("outputDiv"));
sc.__className__ = "'"Some name'"";
sc.setOutput("outputDiv",sc.__className__);
sc.setOutput("outputDiv",sc.setScopeText());
sc.changeClassNameVariable("bar");
sc.setOutput("outputDiv",sc.__className__);
sc.setOutput("outputDiv",sc.setScopeText());

结束 JavaScript 和 CDATA 部分

//]]>
</script>

输出 "div:outputDiv" :

"公共默认类名"

已创建"private [classname] : foo"的新实例。参考 [类名]已创建"公共默认类名"的新实例。参考[这个。类名]

[object HTMLDivElement]

"某个名字"

已创建"private [classname] : foo"的新实例。参考 [类名]已创建"某个名称"的新实例。参考[这个。类名]

酒吧

已创建"private [classname] : foo"的新实例。参考 [类名]已创建柱线的新实例。参考[这个。类名]

->构造函数中声明的类名永远不会改变!->这个。className 或 SomeClass.prototype。类名是公共的,可以更改。

我希望这可能有助于更清楚地理解链条和我的评论......