6

I just got Javascript: The Good Parts by Douglas Crockford and I'm having some difficulty understanding one of his examples regarding prototypes. The code in the book reads as follows:

if (typeof Object.create !== "function") {
    Object.create = function(o) {
        var F = function () {}
        F.prototype = o;
        return new F;
    };
}

I'm assuming that this code is used to target a function's prototype. But why use such a complex approach? Why not just use variable.prototype? Crockford is the leading expert on Javascript so I'm sure there is a good reason for using this model. Can anyone help me understand it better? Any help would be appreciated.

dopatraman
  • 13,416
  • 29
  • 90
  • 154

4 Answers4

5

In ECMAScript 3, the new operator was the only standard way to set the [[Prototype]] internal property of an object, in this case, Crockford is just using a temporary constructor function F for that purpose.

The o argument of that method, is set as the prototype property of the temporary constructor, and by invoking new F(); it builds a new empty object that inherits from F.prototype (see this question for more details about how new works).

For example:

var a = { a: 1 };
var b = Object.create(a); // b inherits from a
b.a; // 1

In the above example, we can say that the b's internal [[Prototype]] property points to a.

Object.getPrototypeOf(b) === a; // true

In other words, b inherits from a.

With the same example, we could use an empty constructor, e.g.:

 function F(){}
 F.prototype = a;

 var b = new F(); // b again inherits from a (F.prototype)

Remember also that the prototype property of functions is different than the [[Prototype]] property that all objects have, the prototype property of functions is used when they are called with the new operator, to build a new object that inherits from that property.

Also, be aware that now, the ECMAScript 5 Standard is being implemented, and this shim, doesn't conform 100% with the spec, in fact, there are some features of the standard Object.create method that cannot be emulated on ES3.

See also:

Community
  • 1
  • 1
Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
  • @CMS--but in this case, `Object.create` is set to an empty function. So there is no inheritance here... right? Also, since `Object.create` is a method of the `Object` constructor, setting it equal to an empty function would be `null` correct? – dopatraman Aug 03 '11 at 21:35
  • @codeninja, I don't get why you say `Object.create` is *set* to an *empty* function, maybe due the last line (`return new F;`)??? That last line just returns a new object invoking the `F` constructor (an object that inherits from `F.prototype`), it might look unfamiliar since the parentheses are missing at the end, but they are optional when you use the `new` operator (`new F();` is equivalent to `new F;`)... – Christian C. Salvadó Aug 03 '11 at 21:40
  • @CMS--The code reads `Object.create = var F` which is set `=` to `function() {}`. doesn't this mean it is in some sense set to an empty function? – dopatraman Aug 03 '11 at 22:06
  • @codeninja, no, the empty function is just *used inside* the parent function (the one that has the `o` parameter), `Object.create` in this example is set to a function that accepts an argument (`o`), builds a temporal function inside its scope (the empty one), and returns a new object that inherits from the `o` argument provided. – Christian C. Salvadó Aug 03 '11 at 22:23
3
var bar = Object.create(foo)

vs.

var bar = new Object()

the first bar has foo as its prototype; the second has Object as its prototype.

Claudiu
  • 224,032
  • 165
  • 485
  • 680
  • Typo: "the second has `Object` as its prototype" should be "the second has `Object.prototype` as its prototype ..." (`Object` is just a constructor function) – Christian C. Salvadó Aug 03 '11 at 21:23
  • @Claudiu--in this case `Object.create` is set to `function()`, it does not assign a prototype to any variable. – dopatraman Aug 03 '11 at 21:24
1

This code is for older JavaScript implementations that do not support Object.create, which is specified in the ECMAScript 5 standard released in November 2009.

Many people say the preferred way to create an object is to specify a prototype for it at the time of creation. This can be called differential inheritance or prototypal inheritance. In fact, that is what Object.create does:

var protoCircle = {x: 0, y: 0, radius: 1, color:"black"};
var myCircle = Object.create(protoCircle);
myCircle.x = 3;
myCircle.color = "green";

This make a green circle of radius 1 centered at (3,0).

The reason the code is so complex that before Object.create was added to JavaScript, the only way to set an object's prototype was to create it with the new operator. Objects created with new got, as their prototype, the value of the constructor's prototype property. It's definitely confusing, but the prototype property is NOT the prototype of an object. Given a function object f, f.prototype is the object that will be assigned as the prototype of all objects constructed through new f(). An object's real prototype is called [[prototype]] or __proto__ but you cannot access these in standard ECMAScript. Confusing, eh?

As a side note. the ES5 specification has a more enhanced Object.prototype specification than the one Crockford defined. It takes a second object for configuring properties of the object being defined.

Ray Toal
  • 86,166
  • 18
  • 182
  • 232
0

This create method will instantiate a new object given the passed object as the prototype.

Nathan Romano
  • 7,016
  • 3
  • 19
  • 18