15

私はプロトタイプの継承とクラスの作成をより深く把握しようとしています (他の方法があることはわかっていますが、この目的のためにプロトタイプを把握しようとしています)。私の質問は次のコード例を使用することです。内にプライベート変数を作成する方法がありTreeFruitそれは関数では返されませんが、プロトタイプ関数genusおよびbulk?には引き続きアクセスできます。

var Tree = function ( name, size ) { 
    this.name = name;
    this.size = size;
};

Tree.prototype.genus = function(){
    return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus');
};
Tree.prototype.bulk = function(){
    return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft';
};


var Fruit = function( name, size ) { 
    this.name = name;
    this.size = size;
};

Fruit.prototype = new Tree();
// Fruit.prototype = Tree.prototype; -- I know this can be used, too.

Fruit.prototype.bulk =  function(){
    return ((typeof this.size !== 'undefined') ? Math.floor(this.size / 2) : '4') + ' lbs';
};

var pine = new Tree('Pine', 9);
var apple = new Fruit('Apple', 6);

console.log(pine.genus(), pine.bulk()); // Outputs: "Pine 9 ft"
console.log(apple.genus(), apple.bulk()); // Outputs: "Apple 3 lbs"

編集:プロトタイプ関数でアクセスできるプライベート変数に置き換えようとしてthis.nameいます。this.size分かりづらくてすみません!

4

4 に答える 4

14

はい。あなたはこれを行うことができます:

(function() {
  var private = "hi";

  Tree.prototype.genus = function(){
    return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus');
  };
  Tree.prototype.bulk = function(){
    return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft';
  };
})();

これで、これらの関数が参照できるプライベート変数が提供されますが、それはプライベートな「クラス」変数になります。つまり、すべてのインスタンスが同じ変数を共有します。インスタンスごとにプライベート変数が必要な場合は、コンストラクター (または「init」メソッドなど) でそれを行う必要があります。つまり、それらのプライベート変数を共有するメソッドもそこで作成する必要があります。(もちろん、構築時にインスタンス メソッドを作成する関数をプロトタイプに配置することもできます。)

編集— このような手法を使用して、jQuery の「.data()」のようなメカニズムを構築し、インスタンスごとの値を保持する場所として機能するクラス変数を作成することができます。それはちょっと不格好ですが、実行可能です。

于 2011-06-10T14:35:46.423 に答える
2

これは、JavaScript の Classes, Private Members, & Prototypal Inheritanceに関するブログ投稿で書いたものです。基本的に、すべてのオブジェクトに固有のプライベート変数アクセサー関数を作成し、それらのプロトタイプ メソッドにそのプライベート アクセサー関数を呼び出して、クロージャー内でのみ使用可能なキーを提供します。

(function(_) {
  Tree = function ( name, size ) { 
    var hidden = {
      name: name,
      size: size
    };
    this._ = function($) {
      return _ === $ && hidden;
    };
  };

  Tree.prototype.genus = function(){
    return ((typeof this._(_).name !== 'undefined') ? this._(_).name : 'Hybridicus Maximus');
  };
  Tree.prototype.bulk = function(){
    return ((typeof this._(_).size !== 'undefined') ? this._(_).size : '8') + ' ft';
  };

  Fruit = function( name, size ) { 
    Tree.apply(this, arguments);
  };
  Fruit.prototype = new Tree();
  // Fruit.prototype = Tree.prototype; -- I know this can be used, too.

  Fruit.prototype.bulk =  function(){
    return ((typeof this._(_).size !== 'undefined') ? Math.floor(this._(_).size / 2) : '4') + ' lbs';
  };
})({});



var pine = new Tree('Pine', 9);
var apple = new Fruit('Apple', 6);

console.log(pine.genus(), pine.bulk()); // Outputs: "Pine 9 ft"
console.log(apple.genus(), apple.bulk()); // Outputs: "Apple 3 lbs"

console.log(pine._(), pine._({})); // Outputs: "false false" because outside of closure

最後の行は、private 変数はクロージャーの外部ではアクセスできないため、アクセサー関数によって利用可能にされない限り、サードパーティ コードによって取得できないことを示していることに気付くでしょう。

于 2013-02-07T20:30:49.283 に答える
0

このように簡単に達成できます

function SharedPrivate(){
  var private = "secret";
  this.constructor.prototype.getP = function(){return private}
  this.constructor.prototype.setP = function(v){ private = v;}
}

var o1 = new SharedPrivate();
var o2 = new SharedPrivate();

console.log(o1.getP()); // secret
console.log(o2.getP()); // secret
o1.setP("Pentax Full Frame K1 is on sale..!");
console.log(o1.getP()); // Pentax Full Frame K1 is on sale..!
console.log(o2.getP()); // Pentax Full Frame K1 is on sale..!
o2.setP("And it's only for $1,795._");
console.log(o1.getP()); // And it's only for $1,795._

クロージャを利用してprivate変数へのアクセス経路を作成し、作成するオブジェクト間でこのアクセスポイントを共有することがポイントであることは言うまでもありません。自然共有のために作成されるオブジェクトのプロトタイプとしてアクセス ポイントを利用するのが理想的なケースです。したがって、同じ機能は、ファクトリ パターンを利用しObject.create()て次のように実現できます。

function SharedPrivate(){
var priv = "secret";
return {gp : function(){return priv},
        sp : function(v){priv = v}
       }
}
sharedProto = SharedPrivate(); // priv is now under closure to be shared
var p1 = Object.create(sharedProto); // sharedProto becomes o1.__proto__
var p2 = Object.create(sharedProto); // sharedProto becomes o2.__proto__

JavaScript プロトタイプ構造は黄金です..!

于 2016-03-06T11:56:55.530 に答える
-1

あなたが与えた内容ではなく、質問のタイトルに基づいてこれを作成しました。ここで同じ質問がありました。

var Tree = function(){

    var outprivatename = "bigsecret"

    var Tre = function(nickname){
        var privatename = "secret that no one should know" 
        this.nickname = nickname
        outprivatename = outprivatename + "-->" + nickname
        this.deepsecret=function(){return privatename + "---" + nickname}
    }

    Tre.prototype.getname=function(){
        console.log(outprivatename+'-----'+this.nickname)
        // console.log(privatename)
      return this.nickname
    }
    return Tre

}
//case one: each has unique closure; `outprivatename` is different for them
var pine = new (Tree())('pine')
var apple = new (Tree())('apple')
pine.getname() //bigsecret-->pine-----pine
apple.getname() //bigsecret-->apple-----apple
console.log(pine.deepsecret()) //secret that no one should know---pine
console.log(apple.deepsecret()) //secret that no one should know---apple

//case one: two share one closure; `outprivatename` is same for both
var Hybrid = Tree()
var hybrid1 = new Hybrid("pinapple1")
var hybrid2 = new Hybrid("pinapple2")

hybrid1.getname() //bigsecret-->pinapple1-->pinapple2-----pinapple1
hybrid2.getname() //bigsecret-->pinapple1-->pinapple2-----pinapple2
console.log(hybrid1.deepsecret()) //secret that no one should know---pinapple1
console.log(hybrid2.deepsecret()) //secret that no one should know---pinapple2

基本的に、関数はその内部のTreeコンストラクターにクロージャーを提供しました。Tre最も深い を使用する代わりに、無名関数privatenameの外側で内側にあるものを使用できます。TreTree

于 2018-03-04T14:01:55.820 に答える