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.
Related
Lets say we have function test():
function test(){
a();
this.b = function(){
alert(1);
}
function a(){
this.b();
}
}
var t = new test();
This code will throw TypeError: this.b is not a function
The question is, how can we correctly access b() from within a()?
Change the order:
function test(){
var me = this;
this.b = function(){
alert(1);
}
a();
function a(){
me.b();
}
}
You can't call this.b() before you've assigned the variable. And you need to use a local variable to capture the value of this in the closure.
function test(){
var me = this;
this.b = function () {
console.log(1);
}
function a() {
console.log('calling me.b()');
me.b();
}
a();
}
var t = new test();
console.log('calling t.b()');
t.b();
I have such a code:
function A() {
this.hello = function() {
console.log("I'm A");
}
}
function B() {
this.hello = function() {
// I need to call A.hello here, like parent.hello();
B.prototype.hello(); // This is wrong, TypeError
console.log("I'm B");
}
}
B.prototype = new A();
var b = new B();
b.hello();
#=> TypeError: Cannot call method 'hello' of undefined
I read some similar questions here but they all use this technique, they assign a method to a prototype.
FaqPage.prototype.init = function(name, faq) {
BasePage.prototype.init.call(this, name);
this.faq = faq;
}
FaqPage.prototype.getFaq = function() {
return this.faq;
}
But it is not in my case. My prototype is a parent's instance. How may call a parent method in my case? Or do I have to refactor my code?
You need to assign the this.hello a value, at the moment you are just creating a function to run.
Try the following :
function A() {
this.hello = function() {
console.log("I'm A");
}
}
function B() {
this.hello = function() {
B.prototype.hello(); // Now runs correctly and logs "I'm A"
console.log("I'm B");
}
}
B.prototype = new A();
var b = new B();
b.hello();
By changing the code to be this.hello = function() { } we are creating a property of the object that can be called from outside the object.
The result of calling b.hello(); is :
I'm A
I'm B
Example JSFiddle
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'; }
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 () {};
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