4

I have a constructor Monkey():

function Monkey(name, age) {
    this.name = name;
    this.age = age;
}

I want to make another constructor named Human() with an extra property cars which will store number of cars the person has along with all the property that Monkey has (like name and age)

I don't want to repeat all the Monkey stuff in the new Human stuff. Is is possible to clone the Monkey and extend a property with prototype?

Santosh Kumar
  • 26,475
  • 20
  • 67
  • 118

3 Answers3

7

I've tried this code, I guess it's what you want:

function Human(name,age,cars){
    Monkey.call(this,name,age);
    this.cars = cars;
}

This way, the Human constructor calls the Monkey constructor as a normal function, but setting its namespace as the new Human object. Thus, in this case, the this keyword inside Monkey constructor refers to a object of class Human, and not Monkey. Also, with this code, the condition new Human() instanceof Human; returns true, since I'm not returning a new instance of Monkey, just using its constructor.

Also, you can "clone" the prototype, as you said. Just do this:

Human.prototype = Monkey.prototype;

EDIT

As @Bergi amd suggested, the best way to clone a prototype is using the Object.create method, as follows:

Human.prototype = Object.create(Monkey.prototype, {constructor:{value:Human}});
Danilo Valente
  • 11,270
  • 8
  • 53
  • 67
  • 2
    `Human.prototype = Object.create(Monkey.prototype, {constructor:{value:Human}});` would be better, else all monkeys are `instanceof Human` and `(new Human).constructor` would be monkey. – Bergi Jan 14 '13 at 03:42
  • @Bergi Thanks, I didn't know about it. I will update the answer – Danilo Valente Jan 14 '13 at 03:44
  • 1
    Actually, you should do both - then you get the methods on the prototype and the side-effects of the constructor. (Or what @Bergi said, but if `Object.create` isn't supported, then it's `Human.prototype = new Monkey(); Human.prototype.constructor = Human;`.) – Ry- Jan 14 '13 at 03:44
  • @minitech: I'm sure it was meant to be both. Btw, you should *not* use `Human.prototype = new Monkey` - you're getting the side effects of the constructor where they are not applicable. There are better ways to shim [`Object.create`](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create) – Bergi Jan 14 '13 at 03:48
  • @Bergi: Yeah, I just meant in this particular case, since the constructor doesn't do anything except set properties. – Ry- Jan 14 '13 at 04:26
  • Also note that `Human.prototype = Monkey.prototype` does not in any way "clone" the prototype object, it just means `Human.prototype` references `Monkey.prototype`, there is one object and no "clone". – RobG Jan 14 '13 at 05:57
0

Simple start for functional style/parasitic'ish inheritance:

function Human(name, age, cars) {
  var that = new Monkey(name, age);
  that.cars = cars;
  return that;
}

As outlined by Douglas Crockford

http://www.crockford.com/javascript/inheritance.html

Matt Whipple
  • 7,034
  • 1
  • 23
  • 34
  • 1
    Yes, but this way the constructor returns an object of type `Monkey`, and not of `Human` (see `new Human() instanceof Human;`) – Danilo Valente Jan 14 '13 at 03:30
  • @MarkLinus "type"? Sounds like you're pulling classical ideas into a far more dynamic space. Relying on things like `instanceof` just bind you to misaligned paradigms in JavaScript. – Matt Whipple Jan 14 '13 at 03:31
  • I'm just saying that, though it's correct, your solution don't solves this problem I described: `new Human()`will not be an instance of class `Human` as expected – Danilo Valente Jan 14 '13 at 03:35
  • @MarkLinus You're answering with bias a question that wasn't asked. Using `instanceof` like that is a form of programming to implementation. Both objects provide the same functionality, and this solution begins by saying it is leaning in the `functional` direction which implies the object has more in common with data than a type system. – Matt Whipple Jan 14 '13 at 03:37
  • I know it wasn't, but this might be a problem in the future, since I don't know how the OP will use this class – Danilo Valente Jan 14 '13 at 03:38
  • Yes, if its thrown into a system that is written tied to implementation it will be one of the many bumps that are encountered and possibly invite kludges. – Matt Whipple Jan 14 '13 at 03:39
  • It is a **functional/parasitic** style constructor which is an alternative to the pseudo-classical style of using the `new` keyword. It says this right before the code. It is a common alternative that you should look into before arguing against. It is far simpler and in my experience saves a lot of people with strong OO background from head scratching as to why things don't work like they seem they should with prorotypal inheritance. – Matt Whipple Jan 14 '13 at 03:49
  • That's OK, but I don't think you should mix the two approaches. At least, please explain the differences/drawbacks or link to a site that does it. – Bergi Jan 14 '13 at 03:53
  • That's fine for you to think that but it's also attaching more impact to the use of `new` than actually exists. If you plan on dealing with JS at length you should be comfortable with both. I'd say you should also stop mentioning using `instanceof` with an implication that it could be used in enforcing a contract which is an invitation for poor design when applied to a classical hierarchy and brings a false sense of security with a language as dynamic as JavaScript. – Matt Whipple Jan 14 '13 at 04:00
0

I'm writing this answer simply to complement the others, it SHOULD NOT be used unless you fully know the impact of using the non-standard __proto__.

function Monkey(name, age) {
    this.name = name;
    this.age = age;
}

function Human(name, age, cars) {
  this.__proto__ = new Monkey(name, age);
  this.cars = cars;
}

console.log(new Human(1, 2, 3));

See also

Community
  • 1
  • 1
Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • Actually I don't think it should be used at all - the inheritance is weird :-) – Bergi Jan 14 '13 at 03:55
  • @Bergi You mean the fact that humans inherit from monkeys? I agree :) Seriously though, the prototype structure doesn't strike me as unintuitive. – Ja͢ck Jan 14 '13 at 03:58
  • 1
    No. Every single human inherits from its own monkey. No human is `instanceof Human`, and `Human.prototype` is useless. – Bergi Jan 14 '13 at 04:04
  • @Bergi That makes sense; but that's also due to the nature of the question itself in a way. – Ja͢ck Jan 14 '13 at 04:06