When is the `.constructor` property of an object actually used - javascript

I've been using code like this for inheriting from another object:
// define base object constructor
function SuperType(){
// constructor code
}
// define base object methods on the prototype
SuperType.prototype.foo = function() {};
// ---------------------------------------------------------------------------
// define object that wants to inherit from the SuperType object
function SubType() {
// call base object constructor with all arguments that might have been passed
SuperType.apply(this, arguments);
// other constructor code
}
// set prototype for this object to point to base object
// so we inherit any items set on the base object's prototype
SubType.prototype = new SuperType();
// reset constructor to point to this object not to SuperType
SubType.prototype.constructor = SubType;
// define any methods of this object by adding them to the prototype
SubType.prototype.myMethod = function() {};
My question is why do you have to set the SubType.constructor = SubType? When is the .constructor property actually used? If you create a SubType object like this:
var s = new SubType();
That's going to call the SubType() constructor regardless of what SubType.prototype.constructor is actually set to, so I'm trying to understand when the .constructor property is ever actually used?
As you can see in this jsFiddle demo with the assignment to .constructor commented out, the proper constructor is still called. So, it appears that the .constructor property is not used in normal construction with the new operator. I'm wondering when it is used?

According to the The ECMAScript Language Specification,
The initial value of Object.prototype.constructor is the standard built-in Object constructor.
In other words, it's just a pointer to the Object's actual, native constructor-- The one that is called via new Object(). Thus, you can override it without changing anything about how new Object() works.
So why does it exist? Because constructor functions are effectively classes in JavaScript, it lets you do certain things with class instances without needing to their class name. To borrow from Axel Rauschmayer's blog, the constructor property allows:
Comparing between classes, i.e. a.constructor === b.constructor
Creating a new instance from an existing instance, i.e. new a.constructor()
Invoking another (super)class's constructor
All without any hardcoded references to class names. Again, it's not really meant to be overridden. To echo the above comments, I've never really seen someone override it in the wild.

Related

Confused on Prototype inheritance Javascript

I found this picture here
In this case, foo is a constructor function and B and C are objects. I am very confused, first off when you create an object does it always come with the properties and proto? Is that the default? Also in terms of the constructor function for foo. Am I correct to say that every proto of a function defaults to Function.prototype, which uses Object.prototype to create an object? The part that is confusing for me is Foo.prototype, when was this prototype created? Does a constructor function always default to the creation of a prototype which a constructor reference set back to itself and a proto set to object?
No wonder there is confusion. The picture is misleading to the point of being incorrect!
Objects created by calling a constructor function with the new keyword have their inheritance chain set to start with the prototype property of the constructor (correct in the picture).
The prototype property is created every time a function is declared using the function keyword to cover the case of the function being use as a constructor later - so you don't need to specify if a function is a constructor or not. For completeness, functions generated by the class keyword also have a prototype property.)
The function's prototype property's constructor property is set to the function when the prototype property is created (meaning when the function is declared). Again the picture is correct: the value of Foo.prototype.constructor is a reference to Foo.
What is wrong in the picture is objects a and b somehow joining together in a reverse fork and their properties becoming available to instances of Foo.
constructor is always an inherited property. If you replace the original prototype property of a function object with another object, you replace the constructor property inherited by objects constructed with the function. Although you can reset the constructor property of a functions prototype property, it's reasonably unusual and not a part of the story the picture is presenting.
If you do modify the inheritance chain by changing a function's prototype property value, the inheritance chain is still always a single threaded chain back to Object.prototype and then null. The inheritance chain never forks as shown in the picture. If you modified Foo.prototype in the picture to make it a or b, the constructor property of Foo instances would not be Foo.
The picture requires a lot of explanation to be useful.
The properties are assigned in the construction function. Any function can be used with new,thus becoming the "construction function".
var f = function(){};
var fInstance = new f();
console.log(fInstance.constructor); // *f*
If there are no properties assigned in that function (using this.propertyName), then the constructed instance will not have properties. If it does, then it will.
// No properties
var f = function(){};
// Two constructor properties, and one default property
var f = function(prop1, prop2){
this.name = prop1;
this.description = prop2;
this.something = "default";
};
If the prototype of the construction function has properties or methods (basically just glorified properties) attached to its prototype, then each instance will have those.
// No prototype
var f = function(){};
// Prototype with one method
var f = function(){};
f.prototype.test = function(){ console.log("hello"); };
The prototypes and properties must be manually created, and may or may not exist. By default, since using new requires a function, there will always be a constructor function. The process of instantiation using new will also always assign the prototype of the constructor to an object containing the constructing function as a property named constructor as well as all of the properties/methods of the construction function's prototype.
In this case, foo is a constructor function and B and C are objects.
Functions are also objects. Everything are objects. unlike classical inheritance where what defined objects are separate entities. Here an object that is an instance of Function is the constructor that will create an instance of its kind that inherits whatever object is on the constructors prototype attribute.
I am very confused, first off when you create an object does it
always come with the properties and proto? Is that the default?
Only way to get the objects own property y is if the constructor function sets this.y. If a property is not found on the object the system will continue to look at the object that was on the constructors prototype field. Some implementations has this as __proto__ but that is not a requirement. It is implementation specific how it is stored on the instance.
Also in terms of the constructor function for foo. Am I correct to say
that every proto of a function defaults to Function.prototype, which
uses Object.prototype to create an object?
function() {...} makes an instance of the constructor Function. All objects except Object itself inherits Object either indirectly or directly, including Function. Basically you can make a function like this:
var f = new Function('a', 'b', 'return a + b');
f is an instance of Function, as you can see. This is almost the same as:
var f = function(a, b) { return a + b; };
Now the first allows for text to be interpreted as code so its less efficient, but I imagine that in the early days these two would be identical in terms of interpretation. Modern engines prefer the last one since it is more predictable while the first can be seen as a specialized eval.
The part that is confusing for me is Foo.prototype, when was this
prototype created? Does a constructor function always default to the
creation of a prototype which a constructor reference set back to
itself and a proto set to object?
Yes. When the function Foo is created, JS creates by default protoype as new Object(), then it sets constructor to itself. The rest needs to be done in the code itself so we know there is something like this after the actual function code to do the rest of the class:
Foo.prototype.x = 10;
Foo.prototype.calculate = function(...) {...};

Why the prototype of instance is not the same like the prototype of its constructor if to use the `Object.getPrototypeOf()` function?

Why the prototype of instance is not the same like the prototype of its constructor if to use the Object.getPrototypeOf() function?
function A(n){this.n=n;};
let a = new A(1);
console.log('Object.getPrototypeOf(a) == Object.getPrototypeOf(A); // ',
Object.getPrototypeOf(a) == Object.getPrototypeOf(A));
console.log('Object.getPrototypeOf(a) == A.prototype; // ',
Object.getPrototypeOf(a) == A.prototype);
Object.getPrototypeOf() returns the value of the internal [[Prototype]] property, which is not the same as the prototype property. When you create a function (or a class), it gets a prototype property, and when you create an instance of it, the created object has the internal [[Prototype]] property set to the prototype property of the class.
Your first example evaluates to false, because [[Prototype]] of a is A.prototype, but [[Prototype]] of A is Function.prototype, because every function is an instance of the Function class.
You are seeing this because A's prototype (the prototype object from which A is derived) is Function.prototype, not A.prototype:
function A(n){this.n=n;};
console.log('Object.getPrototypeOf(A) === Function.prototype');
console.log(Object.getPrototypeOf(A) === Function.prototype);
let a = new A(1);
console.log('Object.getPrototypeOf(a) === A.prototype');
console.log(Object.getPrototypeOf(a) === A.prototype);
Object.getPrototypeOf(x) is not just a convoluted way of writing x.prototype.
Object.getPrototypeOf(x) returns the prototype from which x is derived.
x.prototype is the prototype of objects created using x as a constructor.
Although it seems simple at a glance but the answer will become more clear if you know how protoypal inheritance works in JS.
Still I would try to explain it in short, how prototype works.
In JS, everything is an object. Although primitive values such as numbers, strings, boolean do not look like objects but are treated like objects internally.
For a quick reference see below. Everything is an object.
Now lets come to the case mentioned in question. Whenever you create anything in JS, it uses some existing prototype. It depends on what kind of item you are creating.
The below line is basically doing a lot of things in background. It is creating a function with name as 'A'. While doing so the JS engine uses an already existing special object in the browser called Function.prototype. This contains the basic characteristics of any function that you are creating. Then it creates a brand new object that has only two properties by default: constructor and a link to the default object prototype(referenced by proto). And then assign the new function definition that you have written to this newly created function.
function A(n){this.n=n;};
Hence we have two prototypes to understand here:
Function.prototype
A.prototype
Function.prototype would give that existing object we discussed above which is provided by the engine to create new functions.
A.prototype is the new object that gets created when A is declared. Note that we haven't yet used our new function A to create objects.
While running the below code, JS engine creates a new object which would inherit properties from A.prototype, runs the function definition which is stored in A(this.n = n etc..) and returns the newly created object.
let a = new A(1);
To summarize
a is an object that inherits from A.prototype
A is a function(a special object) that inherits from Function.prototype
I think now it should be clear what the below code means.
Object.getPrototypeOf(a) === A.prototype // true
Object.getPrototypeOf(A) === Function.prototype //true

Whats the difference between JavaScript Inheritance using Prototype and method call? [duplicate]

What does the following code do:
WeatherWidget.prototype = new Widget;
where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.
What is the new keyword doing there and what would happen if it is left out?
WeatherWidget.prototype = new Widget;
The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.
This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.
The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
would be equivalent to
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Other people have implemented similar extensions.
According to some odd Javascript rules, new Widget actually invokes the constructor rather than returning a reference to the constructor. This question actually answers the question the difference between var a = new Widget() and var a = Widget().
In simple words, the new keyword tells Javascript to call the function Widget under a different set of rules than a regular function call. Going off the top of my head, the ones I remember are:
There is a brand new object created
Widget can use the this keyword to refer to that object.
If Widget does not return anything, this new object will be created.
This object will inherit a few additional properties that will indicate it was created by Widget that are used to track down property chains.
Without the new keyword, a call to widget would
If in strict mode, this will be set to undefined.
Otherwise, this will refer to the global object. (Called window by the browser.)
If the function does not return anything, then undefined will be returned.
Reference:
new keyword
WeatherWidget.prototype = new Widget;
does create a new instance of the Widget constructor and use it as WeatherWidget's prototype object. Using the new keyword creates the new object, sets up the inheritance chain of it to Widget.prototype, and applies the constructor function on it (where you can set up individual properties'n'methods, or create private-scoped variables).
Without the new keyword it would be an assignment of the Widget function to the prototype property - which does not make any sense. If you'd add the optional brackets (i.e. Widget()), it would invoke the function normally, but not as a constructor on a new instance, but with the global object as context. See also the reference for the this keyword.
Notice that you should not really use this code. As said, it creates a new instance by invoking the constructor function. But the purpose is only to create an empty object that inherits from the Widgets prototype object, not to instantiate something (which could do some harm, depending on the code). Instead, you should use Object.create (or its popular shim):
WeatherWidget.prototype = Object.create(Widget.prototype);
see also Javascript basic inheritance vs Crockford prototypical inheritance
In plain english you're extending one class with another. A prototype can only be an object so you set WeatherWidget's prototype to a new instance of Widget. If you removed the new keyword you would be setting the prototype to the literal constructor function which doesn't do anything.
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
Understanding that the prototype can be any object, something like this would also work:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
In JavaScript, if the key isn't found on the object, it checks the parents object you extended it from. Hence you can change items on the parent object on the fly like so:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
Note that this all happens during instantiation which means you can't just switch out the prototype after you've created the object:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
However, all modern browsers come with this newer __proto__ method, which allows you to do it:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
Read up more on understanding JavaScript prototypes here.
This article from Pivotal Labs is also really good.
new is important for prototype inheritance; i.e.
Create a constructor with a method
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
Make a second constructor to extend the first with
var ExObj = function(){};
Now, if we prototype without new,
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
Which means we haven't inherited from the prototype of Obj, however, if we prototype with new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
Furthermore, adding new things to the prototype of ExObj doesn't make any changes to it's base, Obj.
JavaScript functions are "MULTIPLE(2) PERSONALITIES"!!!
They are regular-functions with input and output, which we call like function().
Also they are constructors of JS-objects, when we use the new keyword. >>>BUT<<< the new created objects are NOT INSTANCES of the constructors (like the objects of classes in class-based inheritance). The new objects are instances of the object of the prototype property of the constructor.
Then in WeatherWidget.prototype = you put the object you want to inherit its properties to the objects the constructor will create, which usually is new function() and not a function.
JavaScript created HUGE confusion in the programming community by naming the objects created by constructors, INSTANCES of them with the instanceof keyword.
> function f(){}
undefined
> new f() instanceof f
true

Javascript Inheritance and the funny behaviour of 'this' [duplicate]

What does the following code do:
WeatherWidget.prototype = new Widget;
where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.
What is the new keyword doing there and what would happen if it is left out?
WeatherWidget.prototype = new Widget;
The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.
This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.
The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
would be equivalent to
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Other people have implemented similar extensions.
According to some odd Javascript rules, new Widget actually invokes the constructor rather than returning a reference to the constructor. This question actually answers the question the difference between var a = new Widget() and var a = Widget().
In simple words, the new keyword tells Javascript to call the function Widget under a different set of rules than a regular function call. Going off the top of my head, the ones I remember are:
There is a brand new object created
Widget can use the this keyword to refer to that object.
If Widget does not return anything, this new object will be created.
This object will inherit a few additional properties that will indicate it was created by Widget that are used to track down property chains.
Without the new keyword, a call to widget would
If in strict mode, this will be set to undefined.
Otherwise, this will refer to the global object. (Called window by the browser.)
If the function does not return anything, then undefined will be returned.
Reference:
new keyword
WeatherWidget.prototype = new Widget;
does create a new instance of the Widget constructor and use it as WeatherWidget's prototype object. Using the new keyword creates the new object, sets up the inheritance chain of it to Widget.prototype, and applies the constructor function on it (where you can set up individual properties'n'methods, or create private-scoped variables).
Without the new keyword it would be an assignment of the Widget function to the prototype property - which does not make any sense. If you'd add the optional brackets (i.e. Widget()), it would invoke the function normally, but not as a constructor on a new instance, but with the global object as context. See also the reference for the this keyword.
Notice that you should not really use this code. As said, it creates a new instance by invoking the constructor function. But the purpose is only to create an empty object that inherits from the Widgets prototype object, not to instantiate something (which could do some harm, depending on the code). Instead, you should use Object.create (or its popular shim):
WeatherWidget.prototype = Object.create(Widget.prototype);
see also Javascript basic inheritance vs Crockford prototypical inheritance
In plain english you're extending one class with another. A prototype can only be an object so you set WeatherWidget's prototype to a new instance of Widget. If you removed the new keyword you would be setting the prototype to the literal constructor function which doesn't do anything.
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
Understanding that the prototype can be any object, something like this would also work:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
In JavaScript, if the key isn't found on the object, it checks the parents object you extended it from. Hence you can change items on the parent object on the fly like so:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
Note that this all happens during instantiation which means you can't just switch out the prototype after you've created the object:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
However, all modern browsers come with this newer __proto__ method, which allows you to do it:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
Read up more on understanding JavaScript prototypes here.
This article from Pivotal Labs is also really good.
new is important for prototype inheritance; i.e.
Create a constructor with a method
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
Make a second constructor to extend the first with
var ExObj = function(){};
Now, if we prototype without new,
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
Which means we haven't inherited from the prototype of Obj, however, if we prototype with new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
Furthermore, adding new things to the prototype of ExObj doesn't make any changes to it's base, Obj.
JavaScript functions are "MULTIPLE(2) PERSONALITIES"!!!
They are regular-functions with input and output, which we call like function().
Also they are constructors of JS-objects, when we use the new keyword. >>>BUT<<< the new created objects are NOT INSTANCES of the constructors (like the objects of classes in class-based inheritance). The new objects are instances of the object of the prototype property of the constructor.
Then in WeatherWidget.prototype = you put the object you want to inherit its properties to the objects the constructor will create, which usually is new function() and not a function.
JavaScript created HUGE confusion in the programming community by naming the objects created by constructors, INSTANCES of them with the instanceof keyword.
> function f(){}
undefined
> new f() instanceof f
true

What's the difference between these 2 implementations of prototypal inheritance?

What's the difference between these 2 implementations of prototypal inheritance, and considering that we're working with 2 different "prototypes" (the prototype property that's only on functions, and the internal prototype), and how do these implementations differ in their prototype chain lookup? Also, does the first implementation (using the prototype property) rely on our use of the new operator?
Assigning to a functions's prototype property and using the new operator:
function foo() {}
foo.prototype.output = function(){
console.log('inherits from Function.prototype property');
};
bar = new foo();
bar.output();
Storing a function in an object literal and using the Object.create() method:
var foo = {
output: function(){
console.log('inherits from the internal prototype');
}
};
var bar = Object.create(foo);
bar.output();
The main difference is in the way it is used, and the dangers associated.
The first one forces you to use new when you want to create a new object. The syntax is fairly ugly (SomeConstructor.prototype.method), and it bears one major flaw: calling a constructor which adds properties (this.name = nameParam...) without new will apply the construction to the global object. The behaviour of the constructor is weird (create new object which delegates to SomeConstructor.prototype, then apply the constructor to the new object, then if the constructor returns something replace the object by the something). Plus, in your example, foo itself is not usable, you have to create a new object in order to access its functionalities.
The second one, Object.create, doesn't force you to use any syntoxic quirk. You don't have the global pollution risk. The object foo has functionalities that can already be used without creating a new object, and bar will simply borrow these functionalities. This kind of pattern can also make it easier to implement factories (without news to replace everywhere) and object pools if needed.
Eric Eliott talks about it very well, and Kyle Simpson wrote a whole book about prototype delegation!
Now, here's how the lookup happens:
With the constructor, the lookup is done on Constructor.prototype (not the actual internal prototype of the constructor, but its prototypeproperty. If you find it confusing, congratulations, you are human). Additional properties are set in the constructor function. foo itself is not used for the lookup, foo.prototype (again, not the same as foo.__proto__ which points to Function) is the one used for it.
With Object.create the lookup is done on the object itself (foo). There's no prototype non-prototype property on the object.
There's very funny diagrams on this page of Kyle Simpson's book which explain the thing further.
More on new in this question: Is JavaScript's "new" keyword considered harmful?
OK, first of all, in case you didn't know, Object.create is based upon the following pattern proposed by Douglas Crockford (read more here):
function create (proto) {
function f () {}
f.prototype = proto;
return new f();
}
Now, you must be aware that the above code does not yield the same result in case you pass null as parameter.
The ECMAScript algorithm for creating new objects (read more here) states that if the prototype of a function is set to null (or any non object), when you're trying to use new f() syntax, the newly created object will inherit from Object.prototype.
If you use Object.create(null), the newly created object will have its [[Prototype]] internal member set to null, which means the prototype chain will stop there (your object doesn't get hasOwnProperty and other stuff from Object.prototype as normal object would).
var o1 = create(null);
var o2 = Object.create(null);
Object.getPrototypeOf(o1) === Object.prototype // true
Object.getPrototypeOf(o2) === Object.prototype // false
Object.getPrototypeOf(o2) === null // true
The first example - foo, is a function.
The second example - foo is an object.
in the second example, bar becomes an new instance without a constructor.
See - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/create, to add the constructor.
As a side note, it common best practice that constructors should begin with a capital letter.

Categories