8

モジュールパターンの基本と、プライベートメンバーを許可するためのクロージャーの使用について説明しますが、以下のコードがその機能を実行する理由を完全に飲み込むことはできません。

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したがって、ここでキーワードを意図的に省略して、最初の呼び出しはmyCalcCalculatorオブジェクトに設定されます。priv値0で始まり、それが増分されてから、新しいpriv値1が出力されます。

しかし、a)次の呼び出しでCalculator()同じオブジェクトへの参照が返されるのはなぜですか(2番目の「1」で証明されています)。私はnewここで使用してそれを回避できることを知っていますが、なぜそうしなければならないのかわかりません。この関数は、オブジェクトリテラル構文を使用して、基本的に新しいオブジェクトを作成してから返すのではありませんか?privb)同じ関数スタックスペースを使用しているように見えるので(JSでそれを考えるのは正しい方法ですか?)、同じオブジェクトへの参照を返す前に、プロセスで変数をゼロにしないのはなぜですか??

編集:ずさんな/愚かな間違いを修正しました(後継者に感謝します)。これにより、newキーワードを使用しなくても、新しい/別個の計算機オブジェクトが出力されるようになりました。これでa)とb)がクリアされます。結果として得られる質問は、「newモジュールパターンコンストラクターの呼び出しで使用するかどうかは重要ですか。答えは、問題ではないと思います(?)」です。(Joseph:http://jsfiddleを参照してください。 net / MvMvy / 5 / ... instanceof演算子は、どちらの方法でもモジュールパターンでは機能しません。)

4

3 に答える 3

9

他の計算機は出力しませんmyOtherCalc。それらを比較する場合は、3番目の計算機を次のように置き換えますmyCalc.printPriv();

myOtherCalc.printPriv();

次に、出力は次のとおりです。

0
1
0
于 2012-04-18T05:54:49.893 に答える
3

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
于 2012-04-18T06:27:50.257 に答える
0

「新しい」オペレータとは何の関係もありません...ここでは、proto/constructor について十分に説明されたトピックを取得します: 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[

//script : 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"の新しいインスタンスが作成されました。[ className ] の参照 "public default className" の新しいインスタンスが作成されました。【こちらを参考に。クラス名]

[オブジェクト HTMLDivElement]

「ある名前」

"private [ classname ] : foo"の新しいインスタンスが作成されました。[ className ] を参照 「ある名前」の新しいインスタンスが作成されました。【こちらを参考に。クラス名]

バー

"private [ classname ] : foo"の新しいインスタンスが作成されました。[ className ] の参照 bar の新しいインスタンスが作成されました。【こちらを参考に。クラス名]

->コンストラクタで宣言されたclassNameは変更されません! →これ。classNameまたは SomeClass.prototype. classNameは公開されており、変更される可能性があります。

これがチェーンと私のコメントをより明確に理解するのに役立つことを願っています...

于 2012-04-18T07:05:50.730 に答える