javascript inheritance using the prototype property - javascript

I'm trying to do inheritance in javascript. First of all, looking on the web I found this
function A() {}
function B(){}
B.prototype = new A() ;
B.prototype.constructor = B ;
This works, however when I use the prototype property of B it doesn't work anymore ( http://jsfiddle.net/jeanluca/eQBUx/ )
function A() {}
A.prototype.bar = function(){ return 'A'; }
function B() {}
B.prototype.bar = function(){ return 'B'; }
I realize you could do
function B(){ this.bar = function(){ ... } } ;
But I think this is definitely slower than defining it using the prototype. So how could I do inheritance in the second situation ?
Thnx

Here's your code:
function A() {}
A.prototype.bar = function(){ return 'A';}
function B() {}
B.prototype.bar = function(){ return 'B'; }
B.prototype = new A() ; // replaces B's "bar" with A's "bar
var b = new B ;
console.log(b.bar());
As you can see the problem is in your 6th line. You're first setting B.prototype.bar to a function in line 5 and then you immediately set B.prototype to new A in line 6 (effectively undoing what you did in line 5). The solution is to put line 6 before line 5:
function A() {}
A.prototype.bar = function(){ return 'A';}
function B() {}
B.prototype = new A() ; // now it will work
B.prototype.bar = function(){ return 'B'; }
var b = new B ;
console.log(b.bar());
See the demo for yourself: http://jsfiddle.net/eQBUx/1/
In addition I agree with Bergi: Stop using the new keyword.
Update: After reading your comment and understanding your problem in greater detail I would recommend you use my augment library for inheritance:
var A = Object.augment(function () {
this.constructor = function () {};
this.bar = function () {
return "A";
};
});
var B = A.augment(function (base) {
this.constructor = function () {};
this.bar = function () {
return "B" + base.bar.call(this);
};
});
var b = new B;
console.log(b.bar());
See the demo: http://jsfiddle.net/eQBUx/2/

Using this to assign properties breaks the prototype chain. It's very inefficient and you can't use it to get inheritance. So .. don't?

You're creating a property on a the prototype object which you completely replace afterwards. Do it the other way round, create the bar method on the new object. And don't use new!
function B() {}
// first create the prototype object
B.prototype = Object.create(A.prototype);
// then assign properties on it
B.prototype.bar = function(){ return 'B'; }

Related

Javascript : Adding a method to a parent class / to be inherited

I'd like to add a method "bar" to a parent class A, after a subclass B are is defined, so that the method is inherited. Is it possible?
I tried the following code
function A() {
this.foo = function () {
console.log('foo')
}
}
function B() {
A.call(this)
}
// (trying to) add a new method to A
A.prototype.bar = function () {
console.log('bar');
}
// It works with instances of A
var a = new A()
a.foo() // ok
a.bar() // ok
// but not with an instance of B
var b = new B()
b.foo() // this works
b.bar() // not this one <------
/*
Exception: b.bar is not a function
#Scratchpad/3:17:1
*/
Any suggestion, please?
If you need just fix your code, you can link methods like this:
function B() {
A.call(this)
for(var i in A.prototype){ this[i] = A.prototype[i]; }
}
But i think it is bad way.
function A() {
this.foo = function () {
console.log('foo');
};
}
function B() {
A.call(this);
}
// (trying to) add a new method to A
A.prototype.bar = function () {
console.log('bar');
};
B.prototype = Object.create(A.prototype);
// It works with instances of A
var a = new A() ;
a.foo() ; // ok
a.bar() ; // ok
// but not with an instance of B
var b = new B() ;
b.foo() ; // this works
b.bar() ;
I case of functional-type of inheritance - you can't add methods, that don't exists in class. Use prototypes
// if you define the prototype as an object
var A = {
foo: function() {
console.log('foo');
}
};
// and define constructors using Object.create
function newA() {
return Object.create(A);
};
function newB() {
return Object.create(newA());
};
// you can add methods to the prototype
A.bar = function () {
console.log('bar');
};
// it works with instances of A
var a = newA()
a.foo();
a.bar();
// and instances of B
var b = newB();
b.foo();
b.bar();
// you can even modify the prototype after the fact
A.baz = function() {
console.log('baz');
};
// and that will work as well
a.baz();
b.baz();
http://jsfiddle.net/5s8ahvLq/
If you don't want the latter behavior of being able to edit the protoype after the fact, use Object.assign or something like underscore or lodash that provides that functionality:
function newA() {
return Object.create(Object.assign({}, A));
}
You're missing:
B.prototype.__proto__ = A.prototype
If you don't like using __proto__ you can use:
B.prototype = Object.create(A.prototype);

call two function by Inheritance in javascript

I'm new for OOPS JavaScript. Be clear. See my JavaScript code here,
function a(){
this.first = "Kar";
}
function b(){
this.last = "Sho";
}
function c(){
this.getName = function(){
return this.first+this.last;
}
}
c.prototype.u = new a();
c.prototype.v = new b();
var d = new c();
alert(d.getName());
Here, I'm getting following output,
NaN
But I want to print KarSho. Where is problem?
I know following method,
b.prototype = new a();
c.prototype = new b();
Actually what I want is, just call a and b in c. That's it.
Call both a and b in the c constructor.
function a(){
this.first = "Kar";
}
function b(){
this.last = "Sho";
}
function c(){
a.call(this);
b.call(this);
this.getName = function(){
return this.first+this.last;
}
}
var d = new c();
alert(d.getName());
c.prototype.u = new a();
c.prototype.v = new b();
Creates instances of the a and b object on the c.v and c.u prototype properties.
To access them, you would call them by:
function c(){
this.getName = function(){
return this.v.first + this.u.last;
}
}
This is not really inheritance, but rather assigning of properties.

Javascript Prototype Pattern - Feedback

I'm switching from using a Javascript revealing module pattern and what I have below seems to work. What I want to know is if what I'm doing is correct and does it follow best practices. For example, is the way I'm preserving the 'this' state and calling an init function in the constructor correct?
var testApp = function(){
//Kick it off
this.init();
};
testApp.prototype = {
getUsers: function(callback){
//do stuff
},
buildUserTable: function(data){
//do stuff
},
refreshTable: function(){
//Example
this.getUsers();
},
init: function(){
//Preserve 'this'
var instance = this;
//Callback + init
this.getUsers(function(data){
instance.buildUserTable(data);
});
$('.formSection .content').hide();
$('.formSection .content:first').slideDown('slow').addClass('selected');
}
};
window.onload = function () {
var form = new testApp();
};
You're overriding the prototype completely. You can't deal with inheritance that way.
Since {} is an object you are implicitly inheriting from Object but nothing else.
Inheritance looks like this:
function A() {};
function B() {};
B.prototype = new A();
var b = new B();
console.log(b instanceof A); // "true"
B now inherits from A and Object.
If you now do:
B.prototype = {
foo: function () {}
};
var b = new B();
console.log(b instanceof A); // "false"
You're not longer inhering from A;
How to add functions to a prototype? Use this notation:
B.prototype.foo = function () {};

Nesting of classes and this value in JavaScript

Can I write nested classes in Javascript?
function A()
{
this.a;
this.B = function()
{
this.ab ;
this.C = function()
{
this.ab = 0;
}
}
}
If the above code is correct,then
1.How do I declare an object of type B
2.Whose property is ab.A() 's or B() 's?.
3.Inside B() where does the 'this' points to.To A() Or to B()?
In your example, the "classes" will be instance-specific. Are you sure you want that? You might be looking for something more along the lines of:
function A() {
// ...
}
A.B = function() {
// ...
};
var one = new A();
var two = new A.B();
Although the "nested" classes won't be able to access "private members" because JavaScript doesn't have those in the first place.
As for your example:
You would create an instance of A, say new A(), and access B, say new new A().B()1, or replacing new A() with a variable.
Neither, it's an empty statement for now... but it would be a property of the B instance.
To an instance of B (unless Function.call or Function.apply is used).
1 Yes, it works!
Abstract:
Calling to function without using new operator means that this will be refer to object in which that function was created.
For global variables this object is window object.
Calling using new - function behave as constructor like in classes and this refers to this instance which will been created
1.How do I declare an object of type B
First way( as a curiosity ) - by calling to A without using new operator this will be refer to windowobject and B method and all other what was declared with this leaks to global scope because A == window.A => true
A();
var b = new B; // means => new window.B //parentheses can be ommited if you invoking without arguments
alert( ab ) // alerts 'inside A' -> value from code presented below
or from instance of A:
new new A().B // means => new ( new A ).B
Be careful.
2.Whose property is ab.A() 's or B() 's?.
As above, it depends of how we'll accessing to it:
function A()
{
this.ab = "inside A";
this.B = function()
{
this.ab = "inside B";
this.c = function()
{
this.ab = "inside C";
}
}
};
Check this out
var a = new A;
a.ab // "inside A"
a.B(); // in B now 'this' refers to 'a', 'a.ab' will be replaced to 'ab' from inside 'B'
a.ab // "inside B"
but
var a = new A;
a.ab // "inside A"
var b = new a.B;
a.ab // "inside A"
b.ab // "inside B"
// and now
b.c()
b.ab // "inside C" and so on:)
3.Inside B() where does the 'this' points to.To A() Or to B()?
As above:)
It's very unorthodox, but there's nothing stopping you from nesting constructor functions in JavaScript.
From your example, you can access the B function from an instance of A:
var someA = new A();
var someB = new someA.B();
To answer your other question:
this.B = function() {
this.ab = 0;
this.c = function() {
this.ab++;
}
}
What this refers to inside of B depends on how B is invoked. If you call B as a constructor, with the new keyword, this will be a new object inheriting from B's prototype.
If you call B without new, it will be treated as a method, and this will be the instance of A on which the method was called.
And so on with C. If C is called with new, this inside of C will be a new object inheriting from C's prototype. Or C can be a method of B, which makes a lot more sense. Is something like this what you're wanting:
function A() {
this.a;
this.B = function() {
this.ab = 0;
this.c = function() {
this.ab++;
}
}
}
var someA = new A();
var someB = new someA.B();
console.log(someB.ab); //0
someB.c();
console.log(someB.ab); //1
DEMO
Finally, note that, though nesting constructors like this isn't too common, there's nothing stopping you from adding to B's prototype just like you would any other constructor
function A() {
this.a;
this.B = function() {
this.ab = 0;
this.c = function() {
this.ab++;
}
}
this.B.prototype.foo = function() { alert("Bar " + this.ab) };
}
var someA = new A();
var someB = new someA.B();
console.log(someB.ab);
someB.c();
console.log(someB.ab);
someB.foo(); //Bar 1
Updated Demo

Why does this JavaScript example point to the global object (Window)?

function F() {
function C() {
return this;
}
return C();
}
var o = new F();
Break down the component elements.
Suppose you were to do this:
function C() {
return this;
}
var o = C();
There is clearly no object context here, so this is window.
Wrapping that setup in a constructor doesn't change the fact that there isn't any object involved in the context of a straightforward call to C().
function C() is not a method of F, what you need to do is something like this:
function F() {
this.C = function() {
return this;
}
return this.C();
}
var o = new F();
Although that is a bit convoluted, when you could just do this to achieve the same thing:
function F() {}
var o = new F();
C() is not a method of the f object. As in, you can't call o.C();. If that makes sense. and because you return the return value of C() instead of a new instance of C it returns the window object.
function F() { return this; } will also return window. So will var obj = this. It't the value of "this" whenever "this" has no other value.

Categories