1

I've read the MDN document on Object.create. It only pointed out the scenario when the first argument is a prototype. However, I've seen some code in Node.js like this:

var events = require('events');  
var emitter = new events.EventEmitter();  
var a = Object.create(emitter);

So what does Object.create() do when its first argument is an object?

Dmitriy Khaykin
  • 5,238
  • 1
  • 20
  • 32
LASkuma
  • 119
  • 1
  • 6
  • All prototypes are objects. There's no difference - it just does the same. – Bergi Feb 12 '14 at 22:21
  • Then what's the relationship between a and emitter? Are they different from each other? I tried to let emitter listen to event called 'hello' and let a to emit the 'hello' event, emitter could catch it. – LASkuma Feb 12 '14 at 22:27
  • @LASkuma It is the *same* relationship as with *any* prototype. The "question" is then "What does `new events.EventEmitter()` return?" which is different than that asked here. – user2864740 Feb 12 '14 at 22:28
  • @user2864740 It's a little bit confusing. Do you mean 'a' belongs to a subclass of EventEmitter since emitter is an instance of the EventEmitter class? – LASkuma Feb 12 '14 at 22:32
  • @LASkuma: Subclass? Not really. "Subinstance" would match the situation better - it's prototypical inheritance! `a` is an empty object that does inherit properties from the `emitter` object. – Bergi Feb 12 '14 at 22:41
  • @Bergi So can I say that `a` is a "pointer" to the original `emitter` object? Sorry for the bad format above. I'm new to both js and stackOverflow. Thank you for editing that for me. – LASkuma Feb 12 '14 at 22:44
  • 1
    No, it *has* a pointer to `emitter`. It is a new, distinct object, and could have own properties (shadowing the inherited ones). – Bergi Feb 12 '14 at 22:45
  • http://aaditmshah.github.io/why-prototypal-inheritance-matters/ and http://eloquentjavascript.net/chapter8.html are probably the best reads for a start – Bergi Feb 12 '14 at 22:53
  • @Bergi I think I got the point. The reason why the 'hello' event emitted by `a` could be caught is that it copied `emitter`'s '_event' property, which means the event was finally caught by `a` itself, not 'emitter'. Thank you for the resource! – LASkuma Feb 12 '14 at 22:58

2 Answers2

1

The first parameter to Object.create is always the prototype, which is always an object.

In this case it just means that the prototype happens to be created via new - no big deal. If new does (as it should) return a new object, then think of it as a one-off (or "unshared") prototype that will only be used for the new Object.create'd object.

The [prototype] of the Object.create prototype, as established by new, will also be part of the chain, as per standard rules.

See Object.create on MDN:

Object.create(proto [, propertiesObject ])

proto - The object which should be the prototype of the newly-created object.

Community
  • 1
  • 1
user2864740
  • 60,010
  • 15
  • 145
  • 220
  • As I mentioned, I've read that document. Would you please try the code I quoted in your node repl? It does work somehow, I just want to figure out what's going on. – LASkuma Feb 12 '14 at 22:22
  • @LASkuma There *is only one scenario*. A prototype is an object. If it's `new`'d (and no `return sharedInstance` finagling is done) then it's merely a one-off (or "unshared") prototype object - the *object* might as well be created via a new `{}` expression, or it can hide behind a constructor (with normal application of it's own [prototype]) as is this case. *None of the rules have changed.* – user2864740 Feb 12 '14 at 22:23
0

Using Object.create with new to create several instances can cause problems. Using new creates an object that can (and most likely) have instance specific members. If you then use that object to create several instances you will have instance specific members on the newly created object's prototype. Prototype is shared and mutating these members will mutate it for all instances. As the following example demonstrate with the food member.

var Person = function(){
  this.food=[];//every person has food
      // this should be instance specific
};
Person.prototype.eat = function(foodItem){
  this.food.push(foodItem);
};
var proto = Object.create(new Person());
var bob = Object.create(proto);
var ben = Object.create(proto);
bob.eat("Eggs");
console.log(ben.food);//=["Eggs"]
HMR
  • 37,593
  • 24
  • 91
  • 160