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
Related
I am confused as to why after changing constructor property of an object to point to another function still the object is an instance of old constructor
//Original Constructor
function orig_cons() {}
//New Constructor
function new_cons(){}
//Adding property to myfun prototype
new_cons.prototype.x = 1;
//Invoking a new object of 1st constructor
var obj1 = new orig_cons();
//check obj1 instanceof 1st constructor
console.log(obj1 instanceof orig_cons); // true
//Changing constructor property to point to 2nd function
obj1.constructor = new_cons;
//check obj1 instanceof 2nd function
console.log(obj1 instanceof new_cons); // false
Also the prototype property of obj1 is still of original constructor's prototype:
console.log(Object.getPrototypeOf(obj1)); //orig_cons {}
instanceof checks the prototype of the object not the constructor , take this example:
function Person(name){
this.name = name;
}
var p = new Person();
console.log(p instanceof Person); //true
function Func(){}
p.constructor = Func;
console.log(p instanceof Person); // true
Person.prototype = {};
console.log(p instanceof Person); // false
notice how changing the prototype affected instanceof.
From MDN : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
The instanceof operator tests presence of constructor.prototype in
object's prototype chain.
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)
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
Here's the code that explains the question further:
function MyConstructor() {}
var myobject = new MyConstructor();
myobject.constructor == MyConstructor; // true
function MyConstructor() {}
MyConstructor.prototype = {};
var myobject = new MyConstructor();
myobject.constructor == MyConstructor; // false
So, why is the second block false?
The constructor of the created object changes because the constructor of its prototype changes. This is why you generally shouldn't overwrite the prototype. If you do, make sure to set it back later:
function MyConstructor() {}
MyConstructor.prototype = {};
MyConstructor.prototype.constructor = MyConstructor;
…
var myobject = new MyConstructor();
myobject.constructor == MyConstructor; // false
Is there a difference between Object.getPrototypeOf(obj) and obj.constructor.prototype? Or are these two referencing the same thing?
NO
It returns the internal [[Prototype]] value.
For example:
var o = Object.create(null);
Object.getPrototypeOf(o); // null
o.constructor.prototype; // error
var p = {};
var o = Object.create(p);
Object.getPrototypeOf(o); // p
o.constructor.prototype; // Object.prototype
o.constructor.prototype only works with objects created through new ConstructorFunction or where you have manually set the Prototype.prototype.constructor === Prototype relationship.
No. In particular, the constructor property of an object is not always set to what you would consider "correct."
An example of where getPrototypeOf works but .constructor.prototype does not:
function F() { }
F.prototype = {
foo: "bar"
};
var obj = new F();
assert.equal(obj.constructor.prototype, Object.prototype);
assert.equal(Object.getPrototypeOf(obj), F.prototype);
It also fails for typical prototypal inheritance scenarios:
// G prototypally inherits from F
function G() { }
G.prototype = Object.create(F.prototype);
// or: G.prototype = new F();
var obj2 = new G();
assert.equal(obj2.constructor.prototype, Object.prototype);
assert.equal(Object.getPrototypeOf(obj2), G.prototype);
assert.equal(Object.getPrototypeOf(Object.getPrototypeOf(obj2)), F.prototype);