JavaScript field Inheritance weird behaviour - javascript

function A(){
this.a = {};
this.b = 0;
this.Test = function(value){
this.a.x = value;
this.b = value;
};
}
function B(){}
B.prototype = new A;
var b1= (new B());
b1.Test(1);
var b2= (new B());
b2.Test(2);
log(b1.b == 1); //true
log(b2.b == 2); //true
log(b1.a.x == 1);//false x == 2
log(b2.a.x == 2);//true
Why are instances share field a?

This happens because the a object is shared across all instances of B (since the B prototype's is an instance of A).
A workaround would be to assign a new object in your Test method as an own property that shadows the one available on the prototype chain, for example:
function A(){
this.a = {};
this.b = 0;
this.Test = function(value){
this.a = {x: value}; // shadow the object on the prototype chain
this.b = value;
};
}
function B(){}
B.prototype = new A;
var b1= new B();
b1.Test(1);
var b2= new B();
b2.Test(2);
console.log(b1.b == 1); //true
console.log(b2.b == 2); //true
console.log(b1.a.x == 1);//true
console.log(b2.a.x == 2);//true

Related

How to check if a value in this is a prototype value in javascript?

I've got the following code:
function test() {
this.a = 5;
this.b = 6;
}
test.prototype.b = 10;
test.prototype.c = 12;
var example = new test();
How do I find out if example.something:
A. has only a value in the function object?
B. has only a value in the prototype?
C. has a value in both the function object and prototype?
You can test the prototype to see if the value is specified in the prototype with this:
example.constructor.prototype.b
or
Object.getPrototypeOf(example).b
You can test if the property is directly on the object itself (e.g. not inherited or on the direct prototype) with:
example.hasOwnProperty("b")
You can check the properties within the object and its prototype by using the Object.keys method.
function test() {
this.a = 5;
this.b = 6;
}
test.prototype.b = 10;
test.prototype.c = 12;
var example = new test();
console.log(Object.keys(example));
console.log(Object.keys(example.__proto__));
This code reveals this:
function test() {
this.a = 5;
this.b = 6;
}
test.prototype.b = 10;
test.prototype.c = 12;
var example = new test();
for (prop of ['a', 'b', 'c']) {
if (example.hasOwnProperty(prop)) console.log(prop + ' is owned by the object');
if (test.prototype.hasOwnProperty(prop)) console.log(prop + ' is owned by the object prototype');
}

Calling a super function from a subclass function [duplicate]

This question already has answers here:
Javascript Class Inheritance For Functions
(2 answers)
Closed 7 years ago.
I am looking to call a superclass function within a subclass function that overrode the superclass function. For Example:
var a = function(x) {
this.val = x || 0;
};
a.prototype.print = function() {
console.log("Class A");
};
var b = function(x, y) {
this.y = y || 0;
a.call(this, x);
};
b.prototype = Object.create(a.prototype);
b.prototype.constructor = b;
b.prototype.print = function() {
console.log("b inherits from ");
// call to superclass print function (a.print)
};
How would I call the superclass print function from the subclass when the subclass already overwrote the superclass function?
You can use superclass.prototype.method.call(argThis, parameters). In your case without parameters will be a.prototype.print.call(this);
So, your code would be
var a = function(x) {
this.val = x || 0;
};
a.prototype.print = function() {
console.log("Class A");
};
var b = function(x, y) {
this.y = y || 0;
a.call(this, x);
};
b.prototype = Object.create(a.prototype);
b.prototype.constructor = b;
b.prototype.print = function() {
console.log("b inherits from ");
a.prototype.print.call(this);
};

"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');

javascript inheritance and instance variables

I'm trying to understand how inheritance works in JS. Suppose we have a class:
Class = function () {
this.A = 'A';
this.B = 'B';
};
and we are trying to extend it
SubClass = function () {};
SubClass.prototype = new Class();
Do I understance correctly that after inheritance properties A and B are common for all instances of SubClass, since they belong to it's prototype? If yes, how can Class be extended so that A and B do not be part of prototype?
UPD: note that Class uses A and B, so I can't declare them in SubClass.
Thank you in advance!
All I want is to make A and B be accessible and specific for each
"instance"
The typical way of doing this is to pass parameters and assign them to properties. Then you can use call to reference the super class. In other words:
function Person( name, age ) {
this.name = name;
this.age = age;
}
function Student( name, age, grade ) {
Person.call( this, name, age ); // call super-class with sub-class properties
this.grade = grade;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;
var roger = new Student( 'Roger', 18, 'A+' );
You can use properties in parent class without defining:
Class = function () {
this.sum = function() {
return this.a+this.b;
}
};
SubClass = function () {
this.a = 5;
this.b = 6;
};
SubClass.prototype = new Class();
var z = new SubClass();
z.sum(); //11
Another way: Create function in prototype which creates your properties:
Class = function () {
this.makeAB = function() { //called with context of SubClass
this.A = 'A';
this.B = 'B';
}
};
SubClass = function () { this.makeAB() };
SubClass.prototype = new Class();
var z = new SubClass();
z.A = 'AAA';
z.B = 'BBB';
var z2 = new SubClass();
console.log(z)
console.log(z2)

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) { }'

Categories