3

I've been learning prototypical inheritance in JavaScript from John Resig's Secrets of the JavaScript Ninja, and I was wondering what happens in the following code example (that I just made up).

function Person() {}

Person.prototype.sayHello = function() {
    alert("Hello World");
}

function Ninja() {}

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

Ninja.prototype = new Person();

var ninja1 = new Ninja();

As far as I know, the result of all of these lines of code is that the variable ninja1 references a Ninja object, that through its prototype, has the swingSword method, and through prototypical inheritance of Person's prototype, has the sayHello method.

Where I am confused is in the following: since the property swingSword (which happens to be a method) was attached to Ninja's prototype before a person instance was assigned to Ninja's prototype, wouldn't the swingSword property/method be overwritten by the later assignment of the Person instance? If not, how can Ninja's prototype property, which references the prototype object, reference both the Person instance, and have a swingSword property?

Andrew Marshall
  • 95,083
  • 20
  • 220
  • 214
Jay
  • 147
  • 3
  • 11
  • 1
    Did you run the code? What makes you think `ninja1` has both `sayHello` and `swingSword`? – Andrew Marshall Aug 26 '13 at 01:06
  • The prototype of Ninja is completely overwritten when you do `Ninja.prototype = new Person();`. And `ninja1` won't have a swingSword method at the end of this. This is not the way to do prototypical inheritance. – RoryKoehein Aug 26 '13 at 01:07
  • 1
    For inheritance that do not force you to create an in instace of it's parent (new Person) you can use `Ninja.prototype=Object.create(Person.prototype);` or a helper function. More on constructor functions here: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 You're not using instance specific members but if you do you should do `Person.call(this);` in the Ninja constructor body (see the link). – HMR Aug 26 '13 at 02:17
  • if prototypical inheritance, (as upose to mimcing class inheritance with capital letter in function name, constructors and new), is truly important to you, then ditch that book. just because functions use prototype as a key word for function usage, doesn't mean you have your hand fully in the glove of managing prototypes of objects. – klewis Mar 12 '18 at 16:04

1 Answers1

4

[...] that through its prototype, has the swingSword method, [...]

While the rest of that statement is correct -- that ninja1 references Ninja (well, technically, Ninja.prototype) and will have a sayHello through inheritance -- your later thoughts are correct regarding swingSword.

wouldn't the swingSword property/method be overwritten by the later assignment of the Person instance?

At the end of your snippet, ninja1.swingSword should be undefined.

console.log(typeof ninja1.swingSword); // 'undefined'

// as is:
console.log(typeof Ninja.prototype.swingSword); // 'undefined'

After Ninja.prototype = ..., the original prototype object that swingSword was attached to is no longer being referenced. So, it won't be used when creating new instances.


If you intend to set a new prototype object, you'll want make sure that's done before modifying it.

Ninja.prototype = new Person();

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

var ninja1 = new Ninja();

console.log(typeof ninja1.swingSword); // 'function'

And, if ninja1 actually does have a swingSword, it probably means that it was created before the prototype was changed.

Objects retain their own [[Prototype]] reference from when they were created regardless of what changes may be made to their constructor's prototype property.

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

var ninja1 = new Ninja();

Ninja.prototype = new Person(); // won't affect existing instances

var ninja2 = new Ninja();

console.log(typeof ninja1.swingSword); // function
console.log(typeof ninja2.swingSword); // undefined

Example of each: http://jsfiddle.net/G8uTk/

Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199