Understanding Prototypal Inheritance - javascript

var Object1 = {};
var Object2 = new Object();
var Object3 = Object.create({});
When i check whether the prototype is equal to Object.prototype:
The first two return true while the third one returns false.
Why is this happening?
Object.getPrototypeOf(Object1)===Object.prototype //true
Object.getPrototypeOf(Object2)===Object.prototype //true
Object.getPrototypeOf(Object3)===Object.prototype //false

Simply because if you take a look at the Object.create() in the documentation, you will that this method:
creates a new object with the specified prototype object and
properties.
And if you call it with :
Object.create({})
You are not passing a prototype but an empty object with no properties.
So as stated in comments you need to call it like this:
Object.create(Object.prototype)

The Object.create() method creates a new object with the specified prototype object and properties.
Behind the scenes it does the following:
Object.create = (function() {
var Temp = function() {};
return function (prototype) {
if (arguments.length > 1) {
throw Error('Second argument not supported');
}
if (typeof prototype != 'object') {
throw TypeError('Argument must be an object');
}
Temp.prototype = prototype;
var result = new Temp();
Temp.prototype = null;
return result;
};
})();
So the right use would be:
var Object3 = Object.create(Object.prototype);
Or if you want to make your example work:
Object.getPrototypeOf(Object.getPrototypeOf(Object3)) === Object.prototype // true
Here the prototype chain comes into play:
console.dir(Object3)
-> __proto__: Object (=== Your Object Literal)
-> __proto__: Object (=== Object.prototype)

Related

Weird behaviour with constructors

Can someone please explain this behaviour to me.
First let's create a constructor and a new object using the constructor:
var MyConstructor = function() {};
var obj = new MyConstructor();
Everything is as expected:
console.log(obj.constructor === MyConstructor); //true
console.log(obj.__proto__ === MyConstructor.prototype); //true
Let's try again, but this time let's add a custom prototype to the constructor:
var MyConstructor2 = function() {};
var myProto = { fld: 'val' };
MyConstructor2.prototype = myProto;
var obj2 = new MyConstructor2();
Now things are not as I expect them to be:
console.log(obj2.constructor === MyConstructor2); //false?!?!
console.log(obj2.constructor === Object); //true, b-but i didnt use Object..
console.log(obj2.__proto__ === MyConstructor2.prototype); //true
Why is obj2.constructor referring to Object and not MyConstructor2?
--- edit1 ---
Just to clarify. If you create a new function:
var MyConstructor = function() {};
then Javascript implementation will also create a new object:
var temp = { constructor: MyConstructor };
and set it to:
MyConstructor.prototype = temp;
The thing to note here is that the temp object overwrites the constructor field from Object.prototype (and by default Object.prototype.constructor === Object).
So when I create a new object using the constructor:
var obj = new MyConstructor();
then the object inherits the constructor field which points to MyConstructor. In the second case there was no overwriting, so the second object inherited the constructor field directly from Object.prototype.
Each Function object has a prototype property whose "constructor" property is referencing the function. When you create a new prototype using the Object literal syntax, you are created a brand new object whose constructor is literally the Object function. You need to explicitly set the constructor property:
function MyConstructor2() {
}
MyConstructor2.prototype = {
constructor: MyConstructor2
};

How come instance is not undefined [duplicate]

If I return some value or object in constructor function, what will the var get?
function MyConstroctor()
{
//what in case when return 5;
//what in case when return someObject;
}
var n = new MyConstroctor();
what n will get in both cases?
Actually its a quiz question, what will be the answer?
What is returned from a custom object constructor?
a)The newly-instantiated object
b)undefined - constructors do not return values
c)Whatever is the return statement
d)Whatever is the return statement; the newly-instantiated object if no return statement
Short Answer
The constructor returns the this object.
function Car() {
this.num_wheels = 4;
}
// car = { num_wheels:4 };
var car = new Car();
Long Answer
By the Javascript spec, when a function is invoked with new, Javascript creates a new object, then sets the "constructor" property of that object to the function invoked, and finally assigns that object to the name this. You then have access to the this object from the body of the function.
Once the function body is executed, Javascript will return:
ANY object if the type of the returned value is object:
function Car(){
this.num_wheels = 4;
return { num_wheels:37 };
}
var car = new Car();
alert(car.num_wheels); // 37
The this object if the function has no return statement OR if the function returns a value of a type other than object:
function Car() {
this.num_wheels = 4;
return 'VROOM';
}
var car = new Car();
alert(car.num_wheels); // 4
alert(Car()); // No 'new', so the alert will show 'VROOM'
Basically if your constructor returns a primitive value, such as a string, number, boolean, null or undefined, (or you don't return anything which is equivalent to returning undefined), a newly created object that inherits from the constructor's prototype will be returned.
That's the object you have access with the this keyword inside the constructor when called with the new keyword.
For example:
function Test() {
return 5; // returning a primitive
}
var obj = new Test();
obj == 5; // false
obj instanceof Test; // true, it inherits from Test.prototype
Test.prototype.isPrototypeOf(obj); // true
But if the returned value is an object reference, that will be the returned value, e.g.:
function Test2() {
this.foo = ""; // the object referred by `this` will be lost...
return {foo: 'bar'};
}
var obj = new Test2();
obj.foo; // "bar"
If you are interested on the internals of the new operator, you can check the algorithm of the [[Construct]] internal operation, is the one responsible of creating the new object that inherits from the constructor's prototype, and to decide what to return:
13.2.2 [[Construct]]
When the [[Construct]] internal method for a Function object F is called with a possibly empty list of arguments, the following steps are taken:
Let obj be a newly created native ECMAScript object.
Set all the internal methods of obj as specified in 8.12.
Set the [[Class]] internal property of obj to "Object".
Set the [[Extensible]] internal property of obj to true.
Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
If Type(proto) is Object, set the[[Prototype]]` internal property of obj to proto.
If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
If Type(result) is Object then return result.
Return obj.
I found this great link:
JavaScript: Constructor Return Value
The second piece of magic eluded to above is the ability for a
constructor to return a specific, possibly pre-existing object, rather
than a reference to a new instance. This would allow you to manage the
number of actual instances yourself if needed; possibly for reasons of
limited resources or whatnot.
var g_deebee = new Deebee();
function Deebee() { return g_deebee; }
var db1 = new Deebee();
var db2 = new Deebee();
if (db1 != db2)
throw Error("JS constructor returned wrong object!");
else console.log('Equal');
It's as easy as it said in documentation (new operator) :
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
Trying to simplify the existing answers by providing discrete examples proving that:
Only constructors that return primitive or undefined implicitly create a new instance of themselves. Otherwise the exact object returned by the constructor is used as is.
Consider the following constructor that returns exactly what we pass to it. Check the usages:
//A constructor returning the passed value, or not returning at all.
function MyConstructor(obj){
if(obj!==undefined){
return obj;
}
//else do not call return
}
//no value passed (no value is returned from constructor)
console.log((new MyConstructor()) instanceof MyConstructor)
//true
//Primitive passed:
console.log((new MyConstructor(1)) instanceof MyConstructor)
//true
console.log((new MyConstructor(false)) instanceof MyConstructor)
//true
console.log((new MyConstructor("1")) instanceof MyConstructor)
//true
console.log((new MyConstructor(1.0)) instanceof MyConstructor)
//true
//Object passed
console.log((new MyConstructor(new Number(1))) instanceof MyConstructor)
//false
console.log((new MyConstructor({num:1})) instanceof MyConstructor)
//false
console.log((new MyConstructor([1])) instanceof MyConstructor)
//false
console.log((new MyConstructor(MyConstructor)) instanceof MyConstructor)
//false
//Same results if we use: MyConstructor.prototype.isPrototypeOf(new MyConstructor()) e.t.c..
The same rules as above apply also for class constructors. This means that, if the constructor does not return undefined or primitive, we can have the following, which might feel weird to people coming from java:
(new MyClass()) instanceof MyClass //false
Using the same constructor, check in practice how the instance is different when undefined or primitive is returned:
//As above
function MyConstructor(obj){
if(obj!==undefined){
return obj;
}
//else do not call return
}
//Same object passed (same instance to both variables)
let obj = {};
let a1 = new MyConstructor(obj)
let a2 = new MyConstructor(obj)
a1.x=1
a2.x=2
console.log(a1.x === a2.x, a1.x, a2.x)
//true 2 2
//undefined passed (different instance to each variable)
let b1 = new MyConstructor()
let b2 = new MyConstructor()
b1.x=1
b2.x=2
console.log(b1.x === b2.x, b1.x, b2.x)
//false 1 2
//Primitive passed (different instance to each variable)
let c1 = new MyConstructor(5)
let c2 = new MyConstructor(5)
c1.x=1
c2.x=2
console.log(c1.x === c2.x, c1.x, c2.x)
//false 1 2
Additional note: Sometimes a function could act as a constructor even if it is not called as a constructor:
function F(){
//If not called as a constructor, call as a constructor and return the result
if(!new.target){
return new F();
}
}
console.log(F() instanceof F)
//true
console.log(new F() instanceof F)
//true
You shouldn't return anything in a constructor. A constructor is used to initialize the object. In case you want to know what happens is that if you return 5 then n will simply be an empty object and if you return for example { a: 5 }, then n will have a property a=5.
To answer your specific question:
function MyConstructor()
{
return 5;
}
var n = new MyConstructor();
n is an object instance of MyConstructor.
function SomeObject(name) {
this.name = name;
this.shout = function() {
alert("Hello " + this.name)
}
}
function MyConstructor()
{
return new SomeObject("coure06");
}
var n = new MyConstructor();
n.shout();
n is an instance of SomeObject (call n.shout() to prove it)
To make this all absolutely clear...
1) If you return a primitive type, like a number or a string, it will be ignored.
2) Otherwise, you will pass back the object
Functions and constructors are exactly the same in JavaScript, but how you call them changes their behaviour. A quick example of this is below...
function AddTwoNumbers(first, second) {
return first + second;
}
var functionCall = AddTwoNumbers(5, 3);
alert(functionCall);// 8
var constructorCall = new AddTwoNumbers(5, 3);
alert(constructorCall);// object

How does instanceof work in JavaScript?

In the following code sample both checks of obj2 and obj3 at the end with instanceof return true even if the ways there were constructed are different and the results of returning name property are different.
var Obj1 = function() {
this.name = "foo1";
};
Obj1.prototype.name = "foo1onProt";
var obj1 = new Obj1();
var Obj2 = function() {};
Obj2.prototype = new Obj1();
Obj2.prototype.constructor = Obj2;
var obj2 = new Obj2();
var Obj3 = function() {};
Obj3.prototype = Object.create(Obj1.prototype);
Obj3.prototype.constructor = Obj3;
var obj3 = new Obj3();
console.dir(obj1);
console.log("obj1.name: " + obj1.name);
console.dir(obj2);
console.log("obj2.name: " + obj2.name);
console.dir(obj3);
console.log("obj3.name: " + obj3.name);
console.log("obj2 instanceof Obj1: " + (obj2 instanceof Obj1));
console.log("obj3 instanceof Obj1: " + (obj3 instanceof Obj1));
Result of the run in Chrome:
Obj1
name: "foo1"
__proto__: Object
constructor: function () {
name: "foo1onProt"
__proto__: Object
obj1.name: foo1
Obj2
__proto__: Obj1
constructor: function () {}
name: "foo1"
__proto__: Object
constructor: function () {
name: "foo1onProt"
__proto__: Object
obj2.name: foo1
Obj3
__proto__: Object
constructor: function () {}
__proto__: Object
constructor: function () {
name: "foo1onProt"
__proto__: Object
obj3.name: foo1onProt
obj2 instanceof Obj1: true
obj3 instanceof Obj1: true
What is the best way to recognize that obj2 and obj3 are different?
How does actually instanceof work?
What is the best way to recognize that obj2 and obj3 are different?
That will depend a great deal on what you're doing with them. One way would be to use instanceof Obj2 and instanceof Obj3. Since both objects were created with Obj1.prototype in their prototype chain, it makes sense that they identify as being an instance of what we would call the supertype in class-based OOP.
How does actually instanceof work?
The short version
obj instanceof F looks to see if the object referenced by F.prototype is anywhere in obj's prototype chain. It doesn't use constructor at all.
More details
This is covered in the spec by §11.8.5 - The instanceof Operator, which says (indirectly, via §8.6.2) that it calls the [[HasInstance]] internal method of the function object, passing in the object we're testing. Function's [[HasInstance]] (in §15.3.5.3) says that it gets the object reference from the function's prototype property and then returns true if that object is anywhere in the target object's prototype chain, false if it doesn't.
It doesn't use constructor (nothing in JavaScript itself does, in fact) — and if you think about it, it can't, because an object's constructor property can only point at one function, but an object can be instanceof multiple functions — for instance, in the case of pseudo-classical inheritance:
function F1() {}
function F2() {
F1.call(this);
}
F2.prototype = Object.create(F1.prototype);
F2.prototype.constructor = F2;
var obj = new F2();
console.log(obj instanceof F1); // true
console.log(obj instanceof F2); // true
Both are true because the two objects referenced by F1.prototype and F2.prototype are both in obj's prototype chain.
instanceof being true doesn't necessarily mean that obj was created by a call to F, either directly or indirectly; it just indicates there's a vague link between them (F.prototype refers to an object that's also in obj's prototype chain). It usually means F was involved in creating the object, but there's no guarantee.
For instance:
function F() {}
var obj = Object.create(F.prototype);
console.log(obj instanceof F); // true
Note that F wasn't called to create the object, at all.
Or perhaps more clearly and/or dramatically:
function F() {}
var p = {};
var obj = Object.create(p);
console.log(obj instanceof F); // false
F.prototype = p;
console.log(obj instanceof F); // true
There's also this unusual, but entirely possible, version:
function F1() {}
function F2() {}
F1.prototype = F2.prototype = {};
var obj = new F1();
console.log(obj instanceof F2); // true
Or this one:
function F1() {}
function F2() {}
var obj = new F2();
console.log(obj instanceof F1); // false
F1.prototype = F2.prototype;
console.log(obj instanceof F1); // true
Most simply: obj instanceof constructor yields true when obj has constructor's prototype in it's constructor/prototype chain. In other words, your asking your engine whether obj can be treated like an instance of constructor / whether obj behaves like a constructor object.
There is a small handful of syntaxes that allow you to put constructor's prototype in obj's prototype chain. Any and all of them will cause obj instanceof constructor to be true. In your examples, both obj2 and obj3 have Obj1 in their prototype chain.
So, when you ask your javascript engine whether either obj2 or obj3 behave like an instance of Obj1, JavaScript assumes true -- the only case wherein they wouldn't is if you've overridden Obj1's behavior down the line.
function F1() {}
function F2() {
F1.call(this);
}
F2.prototype = Object.create(F1.prototype);
F2.prototype.constructor = F2;
var obj = new F2();
console.log(obj instanceof F1); // true
console.log(obj instanceof F2); // true

JavaScript: instanceof operator

First code:
function MyConstructor() {}
var myobject = new MyConstructor();
MyConstructor.prototype = {};
[ myobject instanceof MyConstructor, // false - why?
myobject.constructor == MyConstructor, // true
myobject instanceof Object ] // true
even though MyConstructor.prototype is replaced myobject still inherits the properties from Myconstructor.prototype. So why is myobject instanceOf Myconstuctor false?
function MyConstructor() {}
MyConstructor.prototype = {};
var myobject = new MyConstructor();
myobject instanceof MyConstructor // true (it is because myobject still inherits from
// Myconstructor.prototype although it has been replaced)
second:
function MyConstructor() {}
MyConstructor.prototype = {};
var myobject = new MyConstructor();
myobject.constructor == MyConstructor; // false (accepted )
So if myobject.constructor is Object why the first: example not pointing it, how can the myobject.constructor still points to MyConstructor since Myconstructor.prototype has changed in first example.
Can you clarify this please?
even though MyConstructor.prototype is replaced myobject still inherits the properties from Myconstructor.prototype.
No. It inherits from the old object which was replaced. And since that object is !== MyConstructor.prototype, the instanceof operator will yield false. In your second example, myobject inherits from the new prototype (the current MyConstructor.prototype), and that's what instanceof tells you.
So if myobject.constructor
The constructor property is completely unrelated to instanceof.
function Constructor() {}
var oldProto = Constructor.prototype;
var oldInstance = new Constructor();
Constructor.prototype = {constructor:"something else"};
var newProto = Constructor.prototype;
var newInstance = new Constructor();
// all these are true:
Object.getPrototypeOf(oldInstance) === oldProto;
Object.getPrototypeOf(newInstance) == newProto;
oldProto !== newProto;
oldProto.constructor === Constructor; // was set implicitly on creating the function
oldInstance.constructor === oldProto.constructor; // inherited
newProto.constructor === "something else"; // if not explicitly set, comes from Object.prototype
newInstance.constructor === newProto.constructor; // inherited
Constructor.prototype === newProto;
newInstance instanceof Constructor; // because the above
Constructor.prototype !== oldProto;
! (oldInstance instanceof Constructor) // because the above

What is returned from a constructor?

If I return some value or object in constructor function, what will the var get?
function MyConstroctor()
{
//what in case when return 5;
//what in case when return someObject;
}
var n = new MyConstroctor();
what n will get in both cases?
Actually its a quiz question, what will be the answer?
What is returned from a custom object constructor?
a)The newly-instantiated object
b)undefined - constructors do not return values
c)Whatever is the return statement
d)Whatever is the return statement; the newly-instantiated object if no return statement
Short Answer
The constructor returns the this object.
function Car() {
this.num_wheels = 4;
}
// car = { num_wheels:4 };
var car = new Car();
Long Answer
By the Javascript spec, when a function is invoked with new, Javascript creates a new object, then sets the "constructor" property of that object to the function invoked, and finally assigns that object to the name this. You then have access to the this object from the body of the function.
Once the function body is executed, Javascript will return:
ANY object if the type of the returned value is object:
function Car(){
this.num_wheels = 4;
return { num_wheels:37 };
}
var car = new Car();
alert(car.num_wheels); // 37
The this object if the function has no return statement OR if the function returns a value of a type other than object:
function Car() {
this.num_wheels = 4;
return 'VROOM';
}
var car = new Car();
alert(car.num_wheels); // 4
alert(Car()); // No 'new', so the alert will show 'VROOM'
Basically if your constructor returns a primitive value, such as a string, number, boolean, null or undefined, (or you don't return anything which is equivalent to returning undefined), a newly created object that inherits from the constructor's prototype will be returned.
That's the object you have access with the this keyword inside the constructor when called with the new keyword.
For example:
function Test() {
return 5; // returning a primitive
}
var obj = new Test();
obj == 5; // false
obj instanceof Test; // true, it inherits from Test.prototype
Test.prototype.isPrototypeOf(obj); // true
But if the returned value is an object reference, that will be the returned value, e.g.:
function Test2() {
this.foo = ""; // the object referred by `this` will be lost...
return {foo: 'bar'};
}
var obj = new Test2();
obj.foo; // "bar"
If you are interested on the internals of the new operator, you can check the algorithm of the [[Construct]] internal operation, is the one responsible of creating the new object that inherits from the constructor's prototype, and to decide what to return:
13.2.2 [[Construct]]
When the [[Construct]] internal method for a Function object F is called with a possibly empty list of arguments, the following steps are taken:
Let obj be a newly created native ECMAScript object.
Set all the internal methods of obj as specified in 8.12.
Set the [[Class]] internal property of obj to "Object".
Set the [[Extensible]] internal property of obj to true.
Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
If Type(proto) is Object, set the[[Prototype]]` internal property of obj to proto.
If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
If Type(result) is Object then return result.
Return obj.
I found this great link:
JavaScript: Constructor Return Value
The second piece of magic eluded to above is the ability for a
constructor to return a specific, possibly pre-existing object, rather
than a reference to a new instance. This would allow you to manage the
number of actual instances yourself if needed; possibly for reasons of
limited resources or whatnot.
var g_deebee = new Deebee();
function Deebee() { return g_deebee; }
var db1 = new Deebee();
var db2 = new Deebee();
if (db1 != db2)
throw Error("JS constructor returned wrong object!");
else console.log('Equal');
It's as easy as it said in documentation (new operator) :
The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead. (Normally constructors don't return a value, but they can choose to do so if they want to override the normal object creation process.)
Trying to simplify the existing answers by providing discrete examples proving that:
Only constructors that return primitive or undefined implicitly create a new instance of themselves. Otherwise the exact object returned by the constructor is used as is.
Consider the following constructor that returns exactly what we pass to it. Check the usages:
//A constructor returning the passed value, or not returning at all.
function MyConstructor(obj){
if(obj!==undefined){
return obj;
}
//else do not call return
}
//no value passed (no value is returned from constructor)
console.log((new MyConstructor()) instanceof MyConstructor)
//true
//Primitive passed:
console.log((new MyConstructor(1)) instanceof MyConstructor)
//true
console.log((new MyConstructor(false)) instanceof MyConstructor)
//true
console.log((new MyConstructor("1")) instanceof MyConstructor)
//true
console.log((new MyConstructor(1.0)) instanceof MyConstructor)
//true
//Object passed
console.log((new MyConstructor(new Number(1))) instanceof MyConstructor)
//false
console.log((new MyConstructor({num:1})) instanceof MyConstructor)
//false
console.log((new MyConstructor([1])) instanceof MyConstructor)
//false
console.log((new MyConstructor(MyConstructor)) instanceof MyConstructor)
//false
//Same results if we use: MyConstructor.prototype.isPrototypeOf(new MyConstructor()) e.t.c..
The same rules as above apply also for class constructors. This means that, if the constructor does not return undefined or primitive, we can have the following, which might feel weird to people coming from java:
(new MyClass()) instanceof MyClass //false
Using the same constructor, check in practice how the instance is different when undefined or primitive is returned:
//As above
function MyConstructor(obj){
if(obj!==undefined){
return obj;
}
//else do not call return
}
//Same object passed (same instance to both variables)
let obj = {};
let a1 = new MyConstructor(obj)
let a2 = new MyConstructor(obj)
a1.x=1
a2.x=2
console.log(a1.x === a2.x, a1.x, a2.x)
//true 2 2
//undefined passed (different instance to each variable)
let b1 = new MyConstructor()
let b2 = new MyConstructor()
b1.x=1
b2.x=2
console.log(b1.x === b2.x, b1.x, b2.x)
//false 1 2
//Primitive passed (different instance to each variable)
let c1 = new MyConstructor(5)
let c2 = new MyConstructor(5)
c1.x=1
c2.x=2
console.log(c1.x === c2.x, c1.x, c2.x)
//false 1 2
Additional note: Sometimes a function could act as a constructor even if it is not called as a constructor:
function F(){
//If not called as a constructor, call as a constructor and return the result
if(!new.target){
return new F();
}
}
console.log(F() instanceof F)
//true
console.log(new F() instanceof F)
//true
You shouldn't return anything in a constructor. A constructor is used to initialize the object. In case you want to know what happens is that if you return 5 then n will simply be an empty object and if you return for example { a: 5 }, then n will have a property a=5.
To answer your specific question:
function MyConstructor()
{
return 5;
}
var n = new MyConstructor();
n is an object instance of MyConstructor.
function SomeObject(name) {
this.name = name;
this.shout = function() {
alert("Hello " + this.name)
}
}
function MyConstructor()
{
return new SomeObject("coure06");
}
var n = new MyConstructor();
n.shout();
n is an instance of SomeObject (call n.shout() to prove it)
To make this all absolutely clear...
1) If you return a primitive type, like a number or a string, it will be ignored.
2) Otherwise, you will pass back the object
Functions and constructors are exactly the same in JavaScript, but how you call them changes their behaviour. A quick example of this is below...
function AddTwoNumbers(first, second) {
return first + second;
}
var functionCall = AddTwoNumbers(5, 3);
alert(functionCall);// 8
var constructorCall = new AddTwoNumbers(5, 3);
alert(constructorCall);// object

Categories

Resources