3

今回「 proto 」を使用する主な理由は、継承定義を関数定義内に保持しようとすることです。

関数 def の外側の継承を設定し、「this.xxx」を介して「パブリック フィールド」にのみアクセスする関数に対してのみ機能し、Inheriting_FuncDef は SuperFuncDef の拡張知識を持っている必要があります。

var G=function (){
    var g1state=0;
    this.g1=function(){
        return g1state++;
    }
};
var E = function (){

    var e2state=0;
    this.e2=function(){
        return e2state++;
    }
};
E.prototype=new G();

var F= function (){

    var f3state=0;
    this.f3=function(){
        return f3state++;
    }
};
F.prototype=new E();


var xx = new F();
var xx2= new F();

console.log("xxg1:___"+xx.g1());//0
console.log("xxg1:___"+xx.g1());//1
console.log("xx2g1:___"+xx2.g1());//2 , need it to be 0, don't wanna share same super() instance/and closure.


console.log("xxe2:___"+xx.e2());//0
console.log("xxe2:___"+xx.e2());//1
console.log("xx2e2:___"+xx2.e2());//2 , need it to be 0;don't wanna share same super() instance/and closure.


console.log("xxf3:___"+xx.f3());//0
console.log("xxf3:___"+xx.f3());//1
console.log("xx2f3:___"+xx2.f3());//0 this f3() is not inherited from super(), and have the expected result. 

console.log(xx);
console.log("xx instanceof E:___"+(xx instanceof E));//ture
console.log("xx instanceof F:___"+(xx instanceof F));//true
console.log("xx instanceof G:___"+(xx instanceof G));//ture

「改良版」の唯一の欠点は、「instancof」テストが正しくないことです。それ以外の場合は、使用できます。しかし、「instantcof」の誤りは大きな欠点です。

//i test it in ie 11, the result is the same.
var G=function (){
    var g1state=0;
    this.g1=function(){
        return g1state++;
    }
};
var E = function (){
    Object.setPrototypeOf(this,new G());
    var e2state=0;
    this.e2=function(){
        return e2state++;
    }
};
//E.prototype=new G();
var F= function (){
    Object.setPrototypeOf(this,new E());
    var f3state=0;
    this.f3=function(){
        return f3state++;
    }
};
//F.prototype=new E();

var xx = new F();
var xx2= new F();

console.log("xxg1:___"+xx.g1());//xxg1:___0  ,expected.
console.log("xxg1:___"+xx.g1());//xxg1:___1  ,expected.
console.log("xx2g1:___"+xx2.g1());//xx2g1:___0  ,expected.


console.log("xxe2:___"+xx.e2());//xxe2:___0  ,expected.
console.log("xxe2:___"+xx.e2());//xxe2:___1  ,expected.
console.log("xx2e2:___"+xx2.e2());//xx2e2:___0  ,expected.


console.log("xxf3:___"+xx.f3());//xxf3:___0  ,expected.
console.log("xxf3:___"+xx.f3());//xxf3:___1  ,expected.
console.log("xx2f3:___"+xx2.f3());//xx2f3:___0  ,expected.


console.log(xx);
console.log("xx instanceof E:___"+(xx instanceof E));//xx instanceof E:___false , expect to be true
console.log("xx instanceof F:___"+(xx instanceof F));//xx instanceof F:___false, expect to be true
console.log("xx instanceof G:___"+(xx instanceof G));//xx instanceof G:___true

したがって、どちらの方法でも完璧な結果を生み出すことはできません。そして、継承セットアップの「Funcref.prototype=new superFuncref()」方法は基本的に機能しないと思います。

そして、私が Object.setPrototypeOf(this,new SuperFuncRef()); を行う唯一の理由は これは、すべての「instantcof」句を true にしたいためです。それ以外の場合は、SuperFuncRef().apply(this) を実行し、最初にすべての関数を「this」にコピーしてから、ローカル オーバーライドを実行します。したがって、新しい F() は F のインスタンスにすぎません。それは私が望んでいたものではありません。

お気遣いありがとうございます。気にしない、または価値がないと思う場合は、放っておいてください。これ以上反対票を投じるのに時間を無駄にしないでください。あなたが答えを出すかどうかにかかわらず、あなたが満足するまで何度でも再フォーマットします。

4

3 に答える 3

2

コンストラクター内ですべてを実行しようとしているのはなぜですか? それは非効率的であり、何の役にも立ちません。__proto__また、まれにそうする必要がない限り、触れるべきではありません。

これは、継承を設定するオーソドックスな方法です (実行中にすべてのメンバー関数の個別のコピーを持たない)。Object.create()ではなくの使用に注意してくださいnew

//test in chrome_v36 only
var G = function() {
};
G.prototype.g1 = function() {};

var E = function() {
};
E.prototype = Object.create(G.prototype); 
E.prototype.e2 = function() {};

var F = function() {
};
F.prototype = Object.create(E.prototype); 
F.prototype.f3 = function() {};

var xx = new F();
console.log(xx); //F {f3: function, e2: function, g1: function}
console.log("xx instanceof E:___" + (xx instanceof E)); // true
console.log("xx instanceof F:___" + (xx instanceof F)); // true
console.log("xx instanceof G:___" + (xx instanceof G)); // true

なんらかの理由ですべてをより封じ込めたい場合は、IIFE を使用できます。

//test in chrome_v36 only
var G = (function() {
   var g = function() {
   };

   g.prototype.g1 = function() {};

   return g;
})();

var E = (function () {
    var e = function() {
    };

    e.prototype = Object.create(G.prototype); 
    e.prototype.e2 = function() {};

    return e;
})();

var F = (function () {
    var f = function() {
    };

    f.prototype = Object.create(E.prototype); 
    f.prototype.f3 = function() {};

    return f;
})();

ただし、これを行うメリットはまったくありません。少なくとも、この単純な例ではそうではありません。

于 2014-10-14T10:10:11.467 に答える
0

答えはこのリンクで提供されているようなものですが、これに対する具体的な答えではありませんが、メカニズムは同じです:

https://stackoverflow.com/a/26300006/289701

私が以前に知らなかった難しい、悲しい真実は次のとおりです。コンストラクターのすべてのインスタンスは同じコンストラクターを持ち、したがって同じconstructor.prototypeであり、FuncDefのすべてのインスタンスに対して唯一の「instance._proto__」はできません偽造される:

function ClassNameHere (){}
var x = new ClassNameHere ();
var x2 = new ClassNameHere ();
console.log(x.__proto__===ClassNameHere.prototype)// true.
console.log(x.__proto__===x2.__proto__)// true.

したがって、「javascript継承」のみを使用してjava_Classのような機能を構築する方法はありません:(private_fields、継承)

私が以前に知らなかった難しい、悲しい真実の 2 番目は、実際、「javascrpit 継承」は一度だけセットアップする必要があるということです。

解決策は、SuperFuncRef.call(this) を使用して SuperFunc のすべてのメソッドをコピーし、それらのコピーされたメソッドの新しいスコープを作成してから、impl オーバーライドを実行することです。その間、「SuperFuncの軽量インスタンス」を使用して、「継承関係/チェーン」を「偽造」/表現します

それが邪悪なコードかどうかはわかりませんが、結果は私が望んでいたものです:

var E= function(c){if(c) return this;

    var ex= 0;
    this.x=function(){
        return ex++;
    };
}

var F= function(c){

    if(!(this instanceof E)){
        this.__proto__.__proto__=new E(true);
    }
    if(c) return this;
    E.call(this);

    var fx=0;
    this.y=function(){
        return fx++;
    };
}

var G= function(c){

    if(!(this instanceof F)){
        this.__proto__.__proto__=new F(true);
    }
    if(c) return this;
    F.call(this);

    var lsuper={};


    var gx=0;

    this.z=function(){
        return gx++;
    };

    if(this.y)lsuper.y=this.y;
    this.y=function(){
        return lsuper.y()+"hehe";
    }
}

var x=new G();
console.log("-------------")
var x2= new G();
console.log("-------------")
var x3= new G();
console.log("x.x():___"+x.x());//0
console.log("x.x():___"+x.x());//1
console.log("x.x():___"+x.x());//2
console.log("x2.x():___"+x2.x());//0, expected, different scope
console.log("x2.y():___"+x2.y());//0hehe

console.log(x);

console.log("x instanceof G:___"+(x instanceof G));//true
console.log("x instanceof F:___"+(x instanceof F));//true
console.log("x instanceof E:___"+(x instanceof E));//true

console.log("x2 instanceof G:___"+(x2 instanceof G));//true
console.log("x2 instanceof F:___"+(x2 instanceof F));//true
console.log("x2 instanceof E:___"+(x2 instanceof E));//true

console.log("x3 instanceof G:___"+(x3 instanceof G));//true
console.log("x3 instanceof F:___"+(x3 instanceof F));//true
console.log("x3 instanceof E:___"+(x3 instanceof E));//true
于 2014-10-15T07:45:00.357 に答える
0

プロトタイプ割り当ての乱用による自己完結型の孤立した継承? できる。

function Class1 () {
   if (!Class1.done) {
      Class1.prototype.meth = function(){}
      Class1.done = true
   }
   this.ownBaseField = 1
}

function Class2 () {
   Class1.call(this)
   if (!Class2.done) {
      Class2.prototype.__proto__ = Class1.prototype
      Class2.done = true
   }
}

function Class3 () {
   Class2.call(this)
   if (!Class3.done) {
      Class3.prototype.__proto__ = Class2.prototype
      Class3.done = true
   }
}

var o = new Class3()
;[o instanceof Class3, o instanceof Class2, o instanceof Class1, 'meth' in o]
// true,true,true,true

この例は演習としてのみ考えてください。この方法は (プロトタイプの割り当てと同様に) 強くお勧めしません。

于 2014-10-14T09:48:44.873 に答える