3

the main reason to use " proto " this time is trying to keep inheritance definition inside function definition:

setup the inheritance out side function def, only works for functions that only access "public fields" through "this.xxx" , and the Inheriting_FuncDef must have the extending knowledge of SuperFuncDef , other wise the "public fields" would happen to collide:

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

for the "improved version",seems the only drawback is that : the "instancof" test can not be correct , otherwise ,it is usable. but the "instancof" incorrectness is a major drawback.

//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

so either way is can't produce the perfect result. and i think the "Funcref.prototype=new superFuncref()" way for inheritance setup basically don't work for me.

and the only reason i do Object.setPrototypeOf(this,new SuperFuncRef()); is because i wanna all "instancof" clause to be true, otherwise , i would do SuperFuncRef().apply(this), copy all the function into "this" first,then do the local override. hence the new F() is only a instanceof F, that is not what i wanted.

thanks for you attention. if you don't care it , or think not worth it , please leave it alone,don't waste more time to down_vote it , i am at the edge of , or you can teach me English grammar by commenting below it . i will re-format it again and again till you satisfy ,despite you give a answer or not.

Johnny
  • 387
  • 2
  • 12
  • Since `__proto__` is deprecated, why do you say "improved" edition ? You should use `Object.setPrototypeOF()` and `Object.getPrototypeOf` see https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Object/proto – laruiss Oct 14 '14 at 07:43
  • Think about it - constructor function could be called many number of time (each time you create object) but setting up functions prototype property is one time activity - it should not be done every time object is created. Also, prototype property should already be set before the constructor function is called - so, how will that happen if you set it inside the constructor... – YK1 Oct 14 '14 at 09:12
  • 哦... very reasonable , i just can't see through, care too much about the writing_convenience, why don't you answer the post ? i will accept it as answer. – Johnny Oct 14 '14 at 09:27
  • however , it is FuncRef.prototype = new SupperInstanceHere(), that's why i think it should call everytime new instance created, other wise,different subInstance share the same superInstance isn't what i wannted, or FuncRef.prototype = new SupperInstanceHere(); just a expression? once i setup like this, each subInstance would have different superInstance? – Johnny Oct 14 '14 at 09:34
  • It's not normal to set up your inheritance _inside_ the constructor. Just set it up outside the constructor. That's the normal way to do it. – JLRishe Oct 14 '14 at 09:56
  • @YK1 you almost got me, but it is not the case. superInstance() need created every-time , i am agree that "inheritance relationship should tell only once" ,however , it is not java or python, in javascript, i don't know a way to tell the "inheritance relationship once only" – Johnny Oct 14 '14 at 11:28
  • TLDR: please shorten the question. On reading the title of the question I thought that the answer would be trivial. However the question itself is too long and complicated. – Aadit M Shah Oct 14 '14 at 11:36

3 Answers3

2

Why are you trying to do everything inside the constructor? That's inefficient and serves no purpose. You also shouldn't be touching __proto__ unless you have some rare need to do so.

Here is an orthodox way to set up inheritance (and not have a separate copy of every member function during execution). Note the use of Object.create() rather than 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

If you want to keep everything more contained for some reason, you can use an 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;
})();

However, I really don't see any benefit in doing this. At least not for this simplistic example.

JLRishe
  • 99,490
  • 19
  • 131
  • 169
0

Self-contained isolated inheritance with prototype assignment abuse? Can be done.

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

Consider this example as exercise only -- the way is strongly discouraged (as prototype assignment is).

Leonid
  • 3,121
  • 24
  • 31
  • 1
    This code should have a big red "never do this" warning on it. It should also use semicolons. (Or were you leaving them out in an attempt to increase the "bad code" factor?) – JLRishe Oct 14 '14 at 09:58
0

the answer is sort of provided in this link , although not specifically answer to this one ,the mechanism is the same:

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

the hard , sad truth that i don't know before is that: every instance of a constructor, have the same constructor, hence the same constructor.prototype, and the only one "instance._proto__" for every instance of a FuncDef can not be faked:

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

so there is no way use only "javascript inheritance" to build java_Class alike feature :(private_fields, inheritance)

the hard , sad truth 2nd that i don't know before is that , indeed , "javascrpit inheritance" only need to be setup once.

the solution is use SuperFuncRef.call(this) to copy all the methods of SuperFunc and create a new scope for those copied methods, then do the impl override. meanwhile , use "light_weight instance of SuperFunc" to "fake"/express the "inheritance_relationship/chain"

i don't know whether it is evil code , but the result is what i wanted:

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
Community
  • 1
  • 1
Johnny
  • 387
  • 2
  • 12