1

申し訳ありませんが、私はおそらくここで本当に初心者です...しかし:

次の JavaScript オブジェクトがあります。

jeeni.TextField = (function(){

    var tagId;

    privateMethod = function(){
        console.log("IN: privateMethod");
    }

    publicMethod = function(){
        console.log("IN: publicMethod: " + this.tagId);
    }

    jeeni.TextField = function(id){
        console.log("Constructor");
        this.tagId = id;
    }

    jeeni.TextField.prototype = {
            constructor: jeeni.TextField,
            foo: publicMethod
    };

    return jeeni.TextField;
 }());

次のコードを実行すると、対応する結果が得られます。

var textField1 = new jeeni.TextField(21); // Outputs: Constructor
textField1.foo();           // Outputs: IN: publicMethod: 21
console.log(textField1.tagId); // Outputs: 21
console.log(textField1.privateMethod); // Outputs: undefined

だから私の質問は、なぜprivateMethod隠されているのか、そうtagIdでないのかということです。両方ともプライベートスコープにしたい。

初心者を助けてください。

ありがとう

4

4 に答える 4

2

モジュールを作成する2つの方法を混同しました。問題は、プライベートvar tagIdがと同じものではないということですthis.tagId

動作し、AMDモジュールで通常行うのと同様のバージョンから始めましょう。

jeeni.TextField = (function(){
//here you can put a variable common to all instances
  return {
  init:function(id){
    var tagId = id;
    console.log("Constructor");

    function privateMethod(){
        console.log("IN: privateMethod");
    }

    function publicMethod(){
        console.log("IN: publicMethod: " + tagId);
    }

    return {
       foo:publicMethod
    };
  }
})();

var textField1 = jeeni.TextField.init(21); //creates instance
textField1.foo();           // Outputs: IN: publicMethod: 21
console.log(textField1.tagId); // Outputs: undefined
console.log(textField1.privateMethod); // Outputs: undefined

これには1つの欠点があります。すべてのオブジェクトインスタンスについて、関数がメモリにコピーされます。それがプロトタイプを使用する唯一の理由です。ただし、プライベート変数が必要な場合は、とにかくRAMを浪費する可能性があります。

コードでは、を置き換えるthis.tagIdtagIdプライベート変数を使用しますが、これはすべてのインスタンスに共通の1つになります。

コードを機能させる方法を見つけたら、コードを機能させて編集することを検討します。

[編集]

スティーブンがしたことは、あなたがあなたのコードがすることを期待したことに近いです。それがどのように機能するのか、そしてその理由を同僚に説明したくはありません。

[編集]

ところで。require.jsとAMD(モジュール定義)を見てください

于 2012-11-25T22:29:43.803 に答える
1

あなたのコードはほぼ正しいです。thistagId にアクセスするときに失うだけです。上で宣言したthis.tagIdものではなく、その特定の TextField にプロパティを設定しています。var tagId

のようにxを使用せずに変数を設定すると、スコープ チェーンを上っていく最も近いものを見つけます。何も見つからない場合は、グローバル オブジェクト ( ) のプロパティになります。あなたの場合、これらの関数は1レベル上に到達できるため、これらの関数のいずれかから変更できます。そのため、「プライベート」変数として使用され、同じ方法で到達できます。varx = 2xwindowtagIdprivateMethod

そして、関数全体からの戻り値に設定されているので、内部でjeeni.TextField参照する必要はありません。jeeni

jeeni.TextField = (function(){

    var tagId;

    var privateMethod = function(){
        console.log("IN: privateMethod");
    }

    var publicMethod = function(){
        console.log("IN: publicMethod: " + tagId);
    }

    function TextField(id){
        // this === the new instance of TextField
        console.log("Constructor", this);
        // set the tagId variable which is in scope here
        tagId = id;
    }

    TextField.prototype.foo = publicMethod

    return TextField

 }()); 

public/private メソッドの前にも追加したことに注意してくださいvar。そうしないと、それらがグローバル スコープにリークされます。を使用することもできますがfunction publicMethod(){ ... }、通常はデバッグに適しています。

混乱している場合x = function(){}...は、 と同じではありませんfunction x(){}「名前付き関数式の解明」の第 2 章を参照してください。

このコードtagIdを使用すると、 TextField のすべてのインスタンス間で共有されるため、これはおそらくあなたが望むものではありません。インスタンスごとに1つ持つ通常の方法は、tagIdそれを「パブリック」プロパティにすることです。これはまさにあなたが行ったことです(idそれ自体は外部から来るので、これには何の問題もありません):

...

// var tagId -> drop this

publicMethod = function(){
    console.log("IN: publicMethod: " + this.tagId);
}

function TextField(id){
    console.log("Constructor");
    this.tagId = id;
}

tagId次に、インスタンスごとにプライベートで固有のものにしましょう。毎回新しい関数を作成せずにこれを行う最も簡単な方法は、tagsすべてのデータを保持するプライベート オブジェクト ( と呼びましょう) を作成し、各インスタンスに独自の ID ( tf_id) を与えることです。ID は表示されますが、tagsオブジェクトはプライベートであるため、パブリック メソッドのいずれかを使用してのみデータにアクセスできます。

jeeni.TextField = (function(){

    var tags = {}
      , uid = 0;

    privateMethod = function(){
        console.log("IN: privateMethod");
    }

    publicMethod = function(){
        console.log("IN: publicMethod: " + tags[this.tf_id].tagId);
    }

    function TextField(id){
        this.tf_id = uid++
        tags[this.tf_id] = id
    }

    TextField.prototype.foo = publicMethod

    return TextField

 }());
于 2012-11-25T22:53:11.147 に答える
0

どうやら私は質問を間違って読んだ。

何かのプロパティ(つまりthis.tagId)を設定すると、すぐに世界中からアクセスできるようになります。コンストラクターを間違った場所にラップしました-代わりに次のように変更してください:

jeeni.TextField = (function(){
    var TextField = function(id){
        console.log("Constructor");
        var tagId = id;
        privateMethod = function(){
            console.log("IN: privateMethod");
        }

        this.publicMethod = function(){
            console.log("IN: publicMethod: " + tagId);
        }
    }

    TextField.prototype = {
            constructor: TextField
    };

    return TextField;
}());

基本的に、これらの保護された変数へのアクセスを必要とするものをプロトタイプに配置することはできません。

于 2012-11-25T22:07:52.910 に答える
0

ここにはいくつかの問題があります。1 つ目は、通常とは異なる方法でグローバル変数をいじっていることです。事実上、これがあります:

var globalVar;

globalVar = function() {
    globalVar = function() {
        //... stuff
    }
    return globalVar;
}

それが何をすることを望んでいますか?これを書く通常の方法は次のとおりです。

function myObj(id) {
    // in javascript the function *is* the constructor
    tagId = id;
    function someMethod() {
        //...
    }
}
var globalVar = new myObj(someId);

ただし、グローバルは避けた方がよいでしょう。

あなたが与える例では、これはあなたが返す実際のオブジェクトです:

 function(id){
    console.log("Constructor");
    this.tagId = id;
}

いいえ、それにはprivateMethodorがありませんpublicMethod。この関数オブジェクトは囲んでいる関数のスコープ内で構築されるため、コンストラクターは にアクセスできますprivateMethod。これは、そのプライバシーが由来する場所です。

JavaScript でプライベート変数とメソッドを実行する方法を確認するには、ウィザード自身に移動します。

http://javascript.crockford.com/private.html

于 2012-11-25T22:36:52.477 に答える