3 Stimmen

Javascript __proto__ produzieren nicht die gleichen Effekte wie die "Prototyp"-Vererbung

Der Hauptgrund, " proto " dieses Mal zu verwenden, besteht darin, zu versuchen, die Vererbungsdefinition innerhalb der Funktionsdefinition beizubehalten:

Die Vererbung außerhalb der Funktionsdefinition einzurichten funktioniert nur für Funktionen, die nur auf "öffentliche Felder" über "this.xxx" zugreifen, und die vererbende Funktionsdefinition muss das erweiternde Wissen der Superfunktionsdefinition haben, da sonst die "öffentlichen Felder" kollidieren könnten:

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 , benötige es, um 0 zu sein, möchte nicht dieselbe super() -Instanz / und closure teilen.

console.log("xxe2:___"+xx.e2());//0
console.log("xxe2:___"+xx.e2());//1
console.log("xx2e2:___"+xx2.e2());//2 , benötige es, um 0 zu sein; möchte nicht dieselbe super() -Instanz / and closure teilen.

console.log("xxf3:___"+xx.f3());//0
console.log("xxf3:___"+xx.f3());//1
console.log("xx2f3:___"+xx2.f3());//0 diese f3() wird nicht von super() geerbt und hat das erwartete Ergebnis. 

console.log(xx);
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

Die einzige Einschränkung für die "verbesserte Version" scheint zu sein, dass der "instancof" -Test nicht richtig sein kann, ansonsten ist sie verwendbar. Aber die Falschheit von "instancof" ist ein großer Nachteil.

//Ich habe es in IE 11 getestet, das Ergebnis ist dasselbe.
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  ,erwartet.
console.log("xxg1:___"+xx.g1());//xxg1:___1  ,erwartet.
console.log("xx2g1:___"+xx2.g1());//xx2g1:___0  ,erwartet.

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

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

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

Also kann keiner der Wege das perfekte Ergebnis liefern. Ich denke, die Vererbungseinrichtung durch "Funcref.prototype=new superFuncref()" funktioniert im Grunde nicht für mich.

Der einzige Grund, warum ich Object.setPrototypeOf(this,new SuperFuncRef()); mache, ist, dass ich möchte, dass alle "instancof" -Klauseln wahr sind, sonst würde ich SuperFuncRef().apply(this) machen, alle Funktionen in "this" kopieren und dann die lokale Überschreibung durchführen. Daher ist new F() nur eine Instanz von F, das ist nicht das, was ich wollte.

Danke für deine Aufmerksamkeit. Falls es dir egal ist oder du es nicht für wichtig hältst, lass es einfach in Ruhe, verschwende keine Zeit damit, es abzulehnen. Ich stehe kurz davor, oder du kannst mir englische Grammatik beibringen, indem du unten kommentierst. Ich werde es immer wieder neu formatieren, bis du zufrieden bist, ob du eine Antwort gibst oder nicht.

2voto

JLRishe Punkte 94883

Warum versuchst du alles im Konstruktor zu erledigen? Das ist ineffizient und dient keinem Zweck. Außerdem solltest du __proto__ nicht anfassen, es sei denn, du hast einen seltenen Bedarf dafür.

Hier ist eine orthodoxe Methode, um Vererbung einzurichten (und während der Ausführung keine separate Kopie jeder Memberfunktion zu haben). Beachte die Verwendung von Object.create() anstelle von new:

//test nur in chrome_v36
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

Wenn du aus irgendeinem Grund alles mehr enthalten halten möchtest, kannst du ein IIFE verwenden:

//test nur in chrome_v36
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;
})();

Ich sehe jedoch wirklich keinen Vorteil darin, das zu tun. Zumindest nicht für dieses einfache Beispiel.

0voto

Leonid Punkte 3041

Isolierte Vererbung mit Missbrauch der Prototypenzuweisung? Möglich.

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

Betrachten Sie dieses Beispiel nur als Übung - der Weg wird dringend davon abgeraten (wie die Prototypzuweisung).

0voto

Johnny Punkte 387

Die Antwort wird irgendwie in diesem Link bereitgestellt, obwohl sie nicht speziell auf diese Antwort zutrifft, der Mechanismus ist jedoch derselbe:

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

die harte, traurige Wahrheit, die ich vorher nicht kannte, ist, dass: jede Instanz eines Konstruktors denselben Konstruktor hat, daher denselben Konstruktor.prototype, und das einzige "instance._proto__" für jede Instanz eines FuncDef nicht gefälscht werden kann:

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

es gibt also keine Möglichkeit, nur "javascript inheritance" zu verwenden, um eine java_Class-ähnliche Funktion zu erstellen :(private_fields, inheritance)

die harte, traurige Wahrheit 2., die ich vorher nicht kannte, ist, dass "javascript inheritance" wirklich nur einmal eingerichtet werden muss.

die Lösung besteht darin, SuperFuncRef.call(this) zu verwenden, um alle Methoden von SuperFunc zu kopieren und einen neuen Bereich für diese kopierten Methoden zu erstellen, dann die Implementierung zu überschreiben. In der Zwischenzeit "light_weight instance of SuperFunc" verwenden, um die "Vererbungsbeziehung/Kette" zu "fälschen"/auszudrücken

ich weiß nicht, ob es böser Code ist, aber das Ergebnis ist das, was ich wollte:

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, erwartet, unterschiedlicher Bereich
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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X