17

Which parameter should i pass for the first parent object from which others will inherit and which one is more efficient

Object.create(Object.prototype)

Object.create(Object)

Object.create(null)  

Object.create(null) returns an empty object

Object.create(Object) returns a function why????( I checked my log and it says function...i used console.dir() )

Object.create(Object) returns a non empty object

How does this whole thing work ... I m more used to the Classname .prototype thing :(

Can't understand what is going on here

Nav
  • 10,304
  • 20
  • 56
  • 83
  • Which one returns a `function`? You've listed `Object.create(Object)` twice and all 3 variations return an object to me. – Fabrício Matté May 21 '13 at 09:15
  • Oh, in Chrome `Object.create(Object)` returns a `function`, I see. Seems like buggy behavior due to passing a Constructor instead of a plain object to be used as prototype. – Fabrício Matté May 21 '13 at 09:17
  • Woah, that's messed up. `var a = Object.create(Object); a.call; // function call() { [native code]}; a(); // TypeError: object is not a function` – phenomnomnominal May 21 '13 at 09:17
  • paste this in your chrome console and see what it returns( note: one line at a time ) var k=Object.create(Object); console.dir(k); check what it returns – Nav May 21 '13 at 09:22
  • 1
    @FabrícioMatté: Not buggy at all, the object is backed by a function as its prototype, so it has function stuff on it. – T.J. Crowder May 21 '13 at 09:25
  • @T.J.Crowder I realized that while elaborating an answer, thanks for putting it in a cleaner way. `=]` – Fabrício Matté May 21 '13 at 09:34
  • FWIW, you only have to use `Object.create` if you want to create a new object which inherits from a specific object. Before that method existed, you either had to set the non-standard `__proto__` property or use a constructor function to create the object. – Felix Kling May 21 '13 at 09:47

2 Answers2

30

Preface: JavaScript uses prototypical inheritance, which means that an object can have (usually does have) a prototype behind it, which is another object. If you try to get the value of a property from an object that it doesn't have, the JavaScript engine looks to the object's prototype (and its prototype, and so on) to find it.

Object.create creates objects. The first argument you give Object.create is the object to use as the prototype of the object it creates. So:

// Create an object with a property 'foo'
var a = {
    foo: 42
};

// Create a blank object using `a` as its prototype
var b = Object.create(a);

// Give `b` a property of its own
b.bar = "hi";

That gives us this in memory:

                           +−−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−−−−−−−+
                           | [[Prototype]] |−−−−−>| (the standard     |
a−−−−−−−−−−−−−−−−−−−−−−+−−>| foo: 42       |      | object prototype) |
                       |   +−−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−−−−−−−+   
                       |
    +−−−−−−−−−−−−−−−+  |
b−−>| [[Prototype]] |−−+
    | bar: "hi"     |
    +−−−−−−−−−−−−−−−+

Proof b uses a:

console.log(b.foo); // 42
a.foo = 67;
console.log(b.foo); // 67

Addressing some of your variations:

var o = Object.create(Object.prototype);

That's exactly the same as var o = {};: It creates a new blank object whose prototype is the object Object.prototype references.

var o = Object.create(Object);

That creates a new blank object o whose prototype is the Object function. It doesn't create a function, just a non-function object that has a function as its prototype. This would be quite odd and probably isn't what you want. :-)

var o = Object.create(null);

Creates a new blank object o whose prototype is null. Since its prototype is null, it doesn't have the usual Object.prototype stuff, like toString and valueOf and hasOwnProperty. That's a bit unusual, although there are use cases for it, such as when you're using an object as a dictionary/map and don't want false positives for those property names. (In ES2015 [aka ES6] another option is to use Map instead.)


As thg435 points out in a comment below, one of the confusing things about JavaScript is that the prototype of an object is a completely different thing from the prototype property you see on functions. It would probably be better if the prototype property had had a different name (although I can't imagine what name it would be without being massively clunky).

An object (let's call it o) has a prototype object it inherits properties from. (In ES2015+ you can get access to that object via Object.getPrototypeOf.) The object on the prototype property of functions is not necessarily the prototype of any object at all. Instead, it's the object that will be assigned as the prototype of any object created via new using that function.

Examples help here.

function Foo() {
}

That function, Foo, has a property Foo.prototype that refers to an object. That object is not, yet, used as the prototype of anything. It's just an object assigned to a property called prototype on the Foo object instance.

var f = new Foo();

Now that object is used as a prototype, specifically it's the prototype of the f object created by the new Foo call.

Ignoring a couple of details, this line of code:

var f = new Foo();

...basically does this:

// Create a blank object, giving it `Foo.prototype` as its prototype
var f = Object.create(Foo.prototype);

// Call` Foo` using that new object as `this`
Foo.call(f);

As I say, that leaves out a couple of details, but hopefully it helps make it clear what the prototype property of functions is for...

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 4
    Probably the biggest source of confusion in javascript is that `x.prototype` and `prototype of x` are different things. – georg May 21 '13 at 09:23
  • @Nav: I've taken a stab at explaining it in an update to the answer. :-) – T.J. Crowder May 21 '13 at 09:36
  • this stuff is really confusing ...anyways suppose I create a constructor function A(){} and want to create a subclass of it so basically what I have to write Object.create(A.prototype) or Object.create(A) ???? – Nav May 21 '13 at 09:48
  • 1
    @Nav: Since you attach methods to `A.prototype` and not to `A`, you would do `Object.create(A.prototype)`. There is no point in having an instance of the sub-class inherit from the parent constructor function (or in general having objects inherit from functions). – Felix Kling May 21 '13 at 09:49
  • yup ..i actually asked cause some of the websites depict this as a way of doing and some the other way... – Nav May 21 '13 at 10:01
  • 1
    @Nav: Yeah, I'm sorry to say you'll find a lot of conflicting (and some downright wrong) ways of doing inheritance in JavaScript looking around the web, especially when you get to hierarchies that are more than just two levels deep (e.g., not just Parent<-Child but Parent<-Child<-Grandchild). FWIW, if you're doing lots of inheritance in JavaScript, you might [find my `Lineage` library](http://code.google.com/p/lineagejs/) useful. (And I'm glad to say that ES6 will basically make that library obsolete, several years from now when ES6 has come out and is well-supported.) – T.J. Crowder May 21 '13 at 10:09
  • I have a doubt regarding `Object.create(Object)` If we pass a empty object to `var myObj = Object.create({});` My Question is simple *Is myObj an empty object or not* – Bharathvaj Ganesan Nov 04 '17 at 14:56
  • @BharathvajGanesan: Yes, `myObj` refers to an empty object (whose prototype is also an empty object, whose prototype is the object from `Object.prototype`). – T.J. Crowder Nov 05 '17 at 09:15
  • @T.J.Crowder But Lodash `_.isPlainObject(Object.create({}));` //=>returns false – Bharathvaj Ganesan Nov 05 '17 at 11:10
  • Even [isPlainObject](https://github.com/sindresorhus/is-plain-obj) by **Sindre Sorus** also returns False Both are plain and empty objects right? – Bharathvaj Ganesan Nov 05 '17 at 11:11
  • 1
    @BharathvajGanesan: So? You asked if it was empty, not if it was "plain." There is no universally accepted definition of a "plain object." The most obvious definition I can think of (inherits directly from `Object.prototype`) would be false for the object returned by `Object.create({})` because it doesn't inherit directly from `Object.prototype`. Whereas an *empty* object would be an object with no properties. – T.J. Crowder Nov 05 '17 at 11:37
2

What is being returned is an object.

>>> typeof Object.create(Object)
<<< "object"
>>> Object.create(Object)
<<< Function {}
//           ^^

Function is the name which Chrome addresses the object's constructor. See How are javascript class names calculated for custom classes in Chrome Dev Tools?


This part of the answer addresses @phenomnomnominal's comment in the question, explaining why the created object has inherits function properties such as call.

The Object constructor is a function, and thus inherits from the Function prototype:

>>> Object.call === Function.prototype.call
<<< true

So an object having Object as prototype will have a link to the Function prototype via prototype chain as well:

>>> Object.create(Object).call === Function.prototype.call
<<< true

And as mentioned by @TJ, using a constructor as prototype is rather odd. You should specify an object as the prototype that the created object will inherit from. @TJ already did a pretty good job explaining this part.

Community
  • 1
  • 1
Fabrício Matté
  • 69,329
  • 26
  • 129
  • 166