Question

I've come across another developer's code which does something like this to define a Javascript type:

function Ninja() {}
Ninja.prototype = {
  swingSword: function(){
    return true;
  }
}

when the more conventional manner is something like:

function Ninja() {}
Ninja.prototype.swingSword = function() {
    return true;
}

The first form mostly works, in that you can create a new instance and call the swingSword method, and instanceof is accurate:

var ninja = new Ninja();
ninja.swingSword(); // returns true
ninja instanceof Ninja; // also true

However, ninja.constructor points to Object rather than the Ninja function. This is an issue for me: I'm trying to access the constructor via an instance, as a workaround for the constructor not being exposed in any other way. But apart from accessing the constructor attribute for reflection/workaround hacks, does the first form cause any significant issues?

Are there any other important attributes of the original Ninja.prototype which might be getting hidden? Will the first form cause any issues with inheriting types, or common libraries?

I'm trying to figure out if this an unusual but acceptable Javascript pattern, or actually a common Javascript misstep or "gotcha" and should be considered a bug.

Note my Ninja example is based on some example code from a tutorial by John Resig. The actual type in question is not called Ninja, and is longer and more complicated.

Also, I've read this guide to constructors and prototypes and understand, eg how prototypes are used in attribute lookups and why isinstanceof still works.

Was it helpful?

Solution

When you "inherit" from another prototype you usually replace the entire prototype, if constructor is important you can re set it to the "correct" value:

var Child = function(){};
//"inherit" from Parent
Child.prototype=Object.create(Parent.prototype);
//reset the constructor
Child.prototype.constructor = Child;

So in your case just repair the constructor after you set the prototype:

var Ninja = function() {}
Ninja.prototype = {
  swingSword: function(){
    return true;
  }
};
// you can put the next line anywhere you want to fix the problem
// http://stackoverflow.com/a/16063711/1641941 under this.constructor
Ninja.prototype.constructor=Ninja;

Or:

var Ninja = function() {}
Ninja.prototype = {
  swingSword: function(){
    return true;
  },
  constructor:Ninja
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top