7

I see a lot of code like this:

function Base() {}
function Sub() {}
Sub.prototype = new Base();

However, if you do:

s = new Sub();
print(s.constructor == Sub);

This is false. This seems confusing to me, since s's constructor is, indeed, Sub. Is it conventional/better to do this?

function Base() {}
function Sub() {}
Sub.prototype = new Base();
Sub.prototype.constructor = Sub;

or does it not really matter?

2
  • I just ran the comparison through an html page as alert(s.constructor == Sub) and it returned true. Commented Dec 31, 2008 at 18:13
  • Many frameworks adjust the constructor property to properly point to the sub class's constructor. I have post that deals with this and other problems in the code you showed above. js-bits.blogspot.com/2010/08/… Commented May 15, 2012 at 0:49

3 Answers 3

9

'constructor' doesn't do what it looks like it does. This, in addition to its non-standardness, is a good reason to avoid using it - stick with instanceof and prototype.

Technically: 'constructor' is not a property of the 's' instance, it is a property of the 'Sub' prototype object showing through. When you create the 'Sub' function in Mozilla, you get a newly-minted default Sub.prototype object which has a 'constructor' pointing back to the Sub function as a courtesy.

However you then replace that prototype with a new Base(). The original default prototype with the link back to Sub is lost; instead, Sub.prototype is an instance of Base without any overriding 'constructor' property. So:

new Sub().constructor===
Sub.prototype.constructor===
new Base().constructor===
Base.prototype.constructor===
Base

...all the way down to the most basic object whose prototype you didn't change.

Is it conventional/better to do this?

When dealing with JavaScript objects/classes there is no one convention; every library's metaclass system behaves slightly differently. I haven't seen one that writes 'constructor' to each derived class manually, but it seems as good a solution as any if you really want to have the real constructor available; it will also make the code compatible with browsers/engines that don't give you 'constructor'.

I'd consider giving it a different name, though, to avoid confusion with the existing and differently-behaving 'constructor' property.

Sign up to request clarification or add additional context in comments.

Comments

3

If you want to test whether an object is exactly an instance of Sub use the instanceof operator:-

print(s instanceof Sub);

If you want to know whether an object is an instance of Sub or an instance of a sub-class of Sub use the isPrototypeOf method:-

print(Sub.prototype.isPrototypeOf(s));

Comments

1

Yeah,

Sub.prototype.constructor = Sub;

let's you use instanceof but there's a better solution. Look here: ,TDD JS Inheritance on GitHub ,and find the Parasitic Combination Inheritance pattern. The code is TDD'd so you should be able to grok it very quickly and then simply change the names to get you started. This is basically what YAHOO.lang.extend uses (source: yahoo employee and author Nicholas Zakas's Professional JavaScript for Web Developer's, 2nd ED, page 181). Good book by the way (not affiliated in any way!)

Why? Because the classical pattern you're working with has staticy reference vars (if you create var arr = [1,2] in the base object, ALL instances will have read/write and will "share state" of 'arr'! If you use constructor stealing you can get around this. See my examples.

Comments

Your Answer

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.