JavaScript: inheritance - javascript

I tried to make inheritance, but I didn't expect that this.array will act like static member. How can I make it 'protected/public':
function A() {
this.array = [];
}
function B() {
this.array.push(1);
}
B.prototype.constructor=B;
B.prototype = new A();
Firebug:
>>> b = new B();
A { array=[1]}
>>> b = new B();
A { array=[2]}
>>> b = new B()
A { array=[3]}

Not "private/protected", but this will make a new Array for each B.
function A() {
this.array = [];
}
function B() {
A.apply(this); // apply the A constructor to the new object
this.array.push(1);
}
// B.prototype.constructor=B; // pointless
B.prototype = new A();

Related

ES6 Instantiating a derived class from an existing instance

Consider the following scenario:
class A {
constructor() {
this.A = 'A';
}
createB() {
//Create a B instance from this current instance
}
}
class B extends A {
constructor() {
super();
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
// Create a B instance from A so that
// a new A isn't instantiated and
// fromInstance.A === 'C'
var fromInstance = base.createB();
I would like to be able to create an instance of B without having to create a new instance of A, but rather use the existing A instance.
My goal is to be able to spawn a B instance by calling a function within A, but also allow a B instance to be created directly and handle constructing a default A.
How can I achieve something like this when B extends A and requires super() to be called?
Not sure this is exactly what you want but it works for your example:
class A {
constructor() {
this.A = 'A';
}
}
class B extends A {
constructor() {
super();
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
// Create a B instance from A so that
// a new A isn't instantiated and
// fromInstance.A === 'C'
var fromInstance = new B();
Object.assign(fromInstance, base);
console.log(fromInstance);
Here is an alternate solution. It is actually pretty common in C# and Java, but since JS has no method overloading, this is kind of cumbersome and not so nice compared to the above solution:
class A {
constructor(source) {
if(source){
//use properties/stuff from source
this.A=source.A;
}
else{
//only perform initialization if source is not provided
this.A = 'A';
}
}
}
class B extends A {
constructor(source) {
super(source);
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
// Create a B instance from A so that
// a new A isn't instantiated and
// fromInstance.A === 'C'
var fromInstance = new B(base);
console.log(fromInstance);
Basically, there are two versions of the constructor, one that creates a completely new object, and one that pretty much copies an old object.
I think there is a bit of a misunderstanding, every instance of B is by definition an instance of A, no matter what you do. If you want super to be called, you are calling the constructor of A, and thus "instantiating" A.
If I understand the problem, you want the new instance's A property to reflect the A property of the instance that created it, right? You can set this in createB since it will be called on A instance. This will allow the B instance to have a property that shadows the inherited A
class A {
constructor() {
this.A = 'A';
}
createB() {
let b = new B()
b.A = this.A // set to the instances 'A'
return b
}
}
class B extends A {
constructor() {
super();
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
// Create a B instance from A so that
// a new A isn't instantiated and
// fromInstance.A === 'C'
var fromInstance = base.createB();
console.log(fromInstance)
A generic approach could copy all A instance properties to a new B instance. An even more generic approach would be to copy the B object's properties to temporary storage first, and write them back later, so that if A and B had the same property name, the B object's property would take precedence:
class A {
constructor() {
this.A = 'A';
}
createB() {
let b = new B();
let temp = {};
let aProp, bProp;
// save own properties of b
Object.keys( b).forEach( bProp => (temp[bProp]=b[bProp]));
// install own properties of A instance
Object.keys( this).forEach( aProp => ( b[aProp]=this[aProp]));
// write back b properties over A instance properties
Object.keys( temp).forEach( bProp=> (this[bProp]=temp[bProp]));
return b;
}
}
class B extends A {
constructor() {
super();
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
// Create a B instance from A so that
// a new A isn't instantiated and
// fromInstance.A === 'C'
var fromInstance = base.createB();
console.log( "derived.A = %s", derived.A);
console.log( "fromInstance.A = %s", fromInstance.A);
Note that in JavaScript terms avoiding Class constructs be syntactically easier because you can change the prototype properties of ordinary functions but not Class constructor functions. However you would probably lose the ability to reliably identify B instances using instanceof B. Using a class expression in CreateB has the same problem - returned objects would not share the same Class constructor.
Just create an instance of B, copy the properties of the current instance of A to it using Object.assign then return it:
createB() {
var b = new B();
Object.assign(b, this);
return b;
}
Example:
class A {
constructor() {
this.A = 'A';
}
createB() {
var b = new B();
Object.assign(b, this);
return b;
}
}
class B extends A {
constructor() {
super();
this.B = 'B';
}
}
var base = new A();
var derived = new B();
base.A = 'C';
var fromInstance = base.createB();
console.log(fromInstance instanceof B);
console.log(fromInstance.A);

"Multiple inheritance" in prototypal inheritance

How can I create a function that inherits from two functions and respects changes for their prototypes when the two base functions don't have an inheritance relationship?
The example demonstrates the behavior I want because c gets modifications to A.prototype and B.prototype.
function A() { }
function B() { }
B.prototype = Object.create(A.prototype);
function C() { }
C.prototype = Object.create(B.prototype);
A.prototype.foo = "foo";
B.prototype.bar = "bar";
var c = new C();
console.log(c.foo); //prints foo
console.log(c.bar); //prints bar
However, I don't have the luxury where B inherits from A.
function A() { }
function B() { }
function C() { }
C.prototype = //something that extends A and B even though B does not extend A.
A.prototype.foo = "foo";
B.prototype.bar = "bar";
var c = new C();
console.log(c.foo); //should print foo
console.log(c.bar); //should print bar
This is not possible.
Try using a mixin pattern, or have a property of C inherit from B and another property inherit from A.
Then access through these properties.
You could change your code to do something like this
C.prototype.perform = function (key) {
var args = Array.prototype.slice(arguments, 1);
if (key in this)
return this[key].apply(this, args);
if (key in B.prototype)
return B.prototype[key].apply(this, args);
if (key in A.prototype)
return A.prototype[key].apply(this, args);
undefined(); // throw meaningful error
}
C.prototype.get = function (key) {
if (key in this)
return this[key];
if (key in B.prototype)
return B.prototype[key];
if (key in A.prototype)
return A.prototype[key];
}
Then use it like
var c = new C();
c.perform('toString');
c.get('foo');

How can I know which object I inherit

In javascript how can I know which object I inehrit?
for example
function a() {
this.c = 1;
}
function b() {
this.d = 2;
}
b.prototype = new a();​
How can I check that b inherit from a?
Thank you.
Use the instanceof operator:
//capital letters indicate function should be used as a constructor
function A() {...}
function B() {...}
B.prototype = new A();
var a,
b;
a = new A();
b = new B();
console.log(a instanceof A); //true
console.log(a instanceof B); //false
console.log(b instanceof A); //true
console.log(b instanceof B); //true
console.log(B.prototype instanceof A); //true
Try this
b.prototype.constructor.name
Working example: http://jsfiddle.net/psrcK/
Use the constructor property of b.prototype or any instance of b.
function a(){
this.c=1;
}
function b(){
this.d=2;
}
b.prototype=new a();
x = new b()
if(x.constructor == a){
// x (instance of b) is inherited from a
}
of you probably want instanceOf.
if (b instanceOf a) {
console.log("b is instance a")
}
This also has the advantage of walking the whole prototype chain so it does not matter if it is a parent, grandparent, etc

JavasScript inheritance for constructors that return a function

Is there a way in JavaScript to inherit from a constructor function that returns a function? For example:
var A = function() {
return function(input) {
// do stuff
};
};
var B = function() {};
B.prototype = new A();
var b = new B();
Thanks
By returning a function from your constructor, you're not creating an instance of A, but rather an instance of the function. Therefore, inheritance will not work.
var A = function() { return function(input) {}; };
var a = new A();
>>> typeof a;
"function"
var A = function() {};
var a = new A();
>>> typeof a;
"object"
If you need B to inherit the returned function from A, you should set it as a method of A, either locally or in the prototype chain, and pass it that way.
var A = function() {
this.method = function(input) {}
};
var B = function() {}
B.prototype = new A();
var b = new B();
>>> b.method
'function(input) { }'

The Benefits of JavaScript Prototype

I've been wondering about JavaScript's prototypal nature, and the benefits of it, and have come down to the following list :
1) Inheritance
cat.prototype = animal
2) Memory Efficiency
a.prototype.b = function() {}
var a1 = new a();
var a2 = new a();
Then a1.b and a2.b are essentially the same object, where as :
var a = function() {
this.b = function() {};
}
var a1 = new a();
var a2 = new a();
a1.b and a2.b would be different function objects and take up more memory.
3) Adding methods/fields to multiple, already created, 'out in the wild' objects.
var a = function() {}
var a1 = new a();
var a2 = new a();
a.prototype.b = function() {}
a1.b();
a2.b();
So the question is, are these correct?
... and are there any other benefits I've missed?
Cheers!
Those are all correct.
Of course, there are "drawbacks" as well:
No closures
function a() {
var ival = 0;
this.start = function(){ ival = setInterval(function(){ }, 300); }
this.finish = function(){ clearTimeout(ival); }
}
compare to:
function a() {
this.ival = 0;
}
a.prototype.start = function(){ this.ival = setInterval(function(){ }, 300); }
a.prototype.finish = function(){ clearTimeout(this.ival); }
http://en.wikipedia.org/wiki/Prototype-based_programming#Comparison_with_class-based_models
Also, please see the discussion of prototype inheritance in the answers to this:
prototype based vs. class based inheritance

Categories