-1

I know little bit C# and now I have started working with JavaScript and I got some problems in understanding the fundamentals.

Here is my code sample:

function BaseFunc(x, y) {
 this.X = x;
 this.Y = y;
}
function DerivedFunc(x, y, z) {
 this.Z = z;
 BaseFunc.call(this, x, y);
}
DerivedFunc.prototype = new BaseFunc; 
 function Test() {
 var d = DerivedFunc(1, 2, 3);
 var b = new BaseFunc(4, 5);
 d.sayHello();
 b.sayHello();
}
DerivedFunc.prototype.sayHello = function () {
 alert("Result is: " + (this.X + this.Y + this.Z));
}

In the above code I am trying to make an inheritance.

Everything looks good until I reach the line BaseFunc.call(this, x, y); this line is supposed to call base function but what is the use of this in this context. Is it just to satisfy the signature of method call, how does it work ?

Second question is, in javascript we can add anything dynamically, In my case I am adding a sayHello() property and assigning it with an anonymous function. like DerivedFunc.prototype.sayHello, am I adding a property/method to BaseFunc or DerivedFunc, as it is added to prototype it should be added to BaseFunc as I understand it. But when I execute the above code I get error that sayHello is not defined.

Can someone please clarify me about what is going wrong, thanks?

asked Dec 17, 2013 at 9:38
6
  • var d = DerivedFunc(1, 2, 3); This is one of the reasons Douglas Crockford go against using "class" in JavaScript in his book: it's syntax correct, no error raised, but you may not got what you want. You may actually mean var d = new DerivedFunc(1, 2, 3). Commented Dec 17, 2013 at 9:49
  • @Passerby: There are a million programming errors that are syntactically correct and don't raise errors, but which don't do what the programmer intended. I don't know why people get so obsessed with this particular one, it's no worse than others. Commented Dec 17, 2013 at 9:52
  • You might benefit from reading the MDN article about object-oriented JavaScript. Commented Dec 17, 2013 at 9:57
  • @ShrShr I "transformed" your code to a pseudo "Class-Oriented" code: pastebin.com/13JWhXkv Commented Dec 17, 2013 at 10:35
  • This question is similar to: How does the "this" keyword work, and when should it be used?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Nov 21, 2024 at 8:01

2 Answers 2

1

Everything looks good until I reach the line BaseFunc.call(this, x, y); this line is supposed to call base function but what is the use of this in this context.

It's there so that within the call to BaseFunc, this has the same value it has in the call to DerivedFunc, so that the lines this.X = x; and such in BaseFunc are assigning to the correct instance. (Calling a function setting a specific value for this is what the .call and .apply methods of functions do.)

But when I execute the above code I get error that sayHello is not defined.

If it's d.sayHello where you're having the trouble, it's because you've missed out the new operator on the line d = DerivedFunc(1, 2, 3);. Since DerivedFunc, when just called as a function and not via new, doesn't have any return value, d will be undefined.


Note that the way you're doing inheritance, though common, has issues. The main issue is here:

DerivedFunc.prototype = new BaseFunc;

You're trying to use a function designed to create instances, and which accepts arguments, in order to create the prototype instance that DerivedFunc will assign to things. What then is BaseFunc supposed to do about the arguments that are missing? Then later, you call it again (from DerivedFunc) to initialize the instance. BaseFunc is doing double-duty.

Here's how you correct that, first the long-winded version:

function x() { }
x.prototype = BaseFunc.prototype;
DerivedFunc.prototype = new x;
DerivedFunc.prototype.constructor = DerivedFunc;

Or if you can rely on ES5's Object.create:

DerivedFunc.prototype = Object.create(BaseFunc.prototype);
DerivedFunc.prototype.constructor = DerivedFunc;

Now we're not calling BaseFunc to create the prototype, but we are still getting its prototype object as the underlying prototype of DerivedFunc's prototype object. We no longer have the problem of what to do with BaseFunc's arguments, and BaseFunc is only called in the way it's designed to be called: To initialize individual instances, not prototypes.

Naturally, rather than writing that for every time we want to have derived constructors, you'd have a helper script for it.

If you're interested in JavaScript inheritance hierarchies, you may want to look at my short Lineage script — not necessarily to use, but to understand how these things work. The page showing how to do things without the script and comparing to doing them with the script may be particularly useful.

answered Dec 17, 2013 at 9:43
Sign up to request clarification or add additional context in comments.

2 Comments

Crowder: Thanks Sir for ur answer I put new and it works for Derived but Why can't I call sayHello on BaseFunc since I added it by saying Derived.prototype.sayHello ?
@ShrShr: Because you didn't add it to BaseFunc.prototype, which is the object assigned as the prototype of instances created via new BaseFunc. Instead, you assigned it to DerivedFunc.prototype, so it's only available to instances created using that as their prototype (the ones created via new DerivedFunc in this case). While DerivedFunc.prototype uses BaseFunc.prototype as its prototype, they're separate objects, adding properties to DerivedFunc.prototype has no effect on BaseFunc.prototype.
-1

Hi please go through the following. I hope it will give you some idea about inheritence and call()

<script type="text/javascript"> 
 //inheritence
 function parent() {
 this.add = function (a, b) {
 return a + b;
 }
 this.subtract = function (a, b) {
 return a - b;
 }
 }
 function child() {
 this.display = function () {
 alert(this.add(11, 23));
 }
 }
 child.prototype = new parent(); //child extends parent.... inheritence
 child.prototype.constructor = child; //resetting constructor property
 var obj = new child();
 obj.display();
 /*
 .call() and .apply()
 They allow our objects to borrow methods from other objects and invoke them as their own
 */
 var person = {
 name: 'Kundan',
 display: function(name) {
 alert(this.name + ' welcomes ' + name);
 }
 };
 person.display('Dipa'); //Kundan welcomes Dipa
 var person1 = { name: 'Java Master' };
 person.display.call(person1, 'Sachin'); //Java Master welcomes Sachin
 //here person1 object is passed in the call function
 //if we are using call inside a function and want to pass the same function object then this is passed in call function
 /*
 We can pass more parameters as follows
 person.display.call(person1, 'a', 'b', 'c');
 The method apply() works the same way as call() but with the difference that all parameters you want to pass to the method of the other object are passed as an array.
 */
 person.display.apply(person1, ['a', 'b', 'c']);
</script>
answered Dec 17, 2013 at 10:18

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.