21

Why do these 2 implementations behave differently? What exactly sets them apart when it comes to evaluating their prototypes?

Creating an object with the prototype specified:

   function Foo() {}

   // creates an object with a specified prototype
   var bar = Object.create(Foo);

   console.log(Object.getPrototypeOf(bar)); // returns: function Foo(){}
   console.log(Foo.isPrototypeOf(bar)); // returns: true

Creating an object with the constructor method:

   function Foo() {}

   // creates an object with the constructor method    
   var bar = new Foo();

   console.log(Object.getPrototypeOf(bar)); // returns: Foo {}
   console.log(Foo.isPrototypeOf(bar)); // returns: false

Also, why does the second implementation return both Foo {} and false?

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
shmuli
  • 5,086
  • 4
  • 32
  • 64
  • 1
    "Also, why does the second implementation return both Foo {} and false?" is a great question. I've updated my answer to address it. – joews Apr 12 '15 at 19:27
  • 3
    Note that you would usually do `var bar = Object.create( Foo.prototype );`, which gives you the expected behaviour. – Paul Apr 12 '15 at 22:02
  • possible duplicatet of [Understanding the difference between `Object.create()` and `new SomeFunction()`](http://stackoverflow.com/q/4166616/1048572) – Bergi Apr 13 '15 at 00:11

2 Answers2

22

Object.create(Foo) means "create an object with Foo as the prototype".

new Foo() means "Create an object with Foo.prototype as the prototype and Foo as the constructor".

Therefore Foo is the prototype of Bar in the first example and the constructor of Bar in the second example.

I think the second part of your question is prompted by misleading console output - Object.getPrototypeOf(bar) actually returns Foo.prototype, not Foo:

function Foo() {}
var bar = new Foo();

Object.getPrototypeOf(bar) === Foo
// -> false

Object.getPrototypeOf(bar) === Foo.prototype
// -> true
joews
  • 29,767
  • 10
  • 79
  • 91
11

When you use the 'new' keyword to instantiate an object JavaScript actually adds in two lines of code to your object.

If you intend to create an object with pseudoclassical instantiation you create your object like this:

var Foo = function() {
this.property = 'baz';
};

When you call var bar = new Foo() Javascript runs Foo as the following:

var Foo = function() {
// ADDED CODE: var this = Object.create(Foo.prototype);
this.property = 'baz';
// ADDED CODE: return this;

Using Object.create creates a delegation relationship from the newly created object to the specified object, so in your first case bar is delegating its lookups to Foo, but in the second case the lookups are delegated to Foo.prototype.

You may find this blog post interesting. It goes into Pseudoclassical instantiation (using the new keyword) as opposed to Prototypal instantiation, which does not use the new keyword.

ChadF
  • 1,750
  • 10
  • 22