My JavaScript says that instanceof
operator search for if the prototype property is present on the constructor or not.
String instanceof Object; // true
String.prototype === Object.prototype; // false
String.prototype.prototype === Object.prototype; // false
String.prototype.prototype.prototype === Object.prototype; // Throws into "Cannot read property 'prototype' of undefined"
String.prototype.prototype; // undefined
That simply means Object.prototype is not present on String.prototype chain.
Which has confused me then how come String instanceof Object
is returning true?
Your JavaScript is not lying to you :D. It is true that instanceof
operator tests if the prototype property of a Constructor is present on the Object prototype chain or not.
You are just missing the fact that functions have dual life in JavaScript. They are Function and Object as well at the same time. When you are testing the following code
String instanceof Object
; // true
String
in this above code is actually an object which you are referring to. Now let's run the following validation:
String.__proto__ === Object.prototype
; //false
String.__proto__.__proto__ === Object.prototype
; //true
And that's the 'true'
you were looking for :) And that reflects that Object.prototype is present on the String proto chain.
Note: "Use proto with a caution"
The use of __proto__ is controversial, and has been discouraged by many. It was never originally included in the EcmaScript language spec, but modern browsers decided to implement it anyway. Today, the __proto__ property has been standardized in the ECMAScript 6 language specification and will be supported into the future. Still, mutating the [[Prototype]] of an object is a slow operation that should be avoided if performance is a concern.
The other way you can try traversing the prototype chain and avoid proto is as follows:
Object.getPrototypeOf(String.prototype) === Object.prototype;
Hope this helps. Happy JavaScript.
Yes, String
is instanceof Object
, because String
is a function, and functions are objects in JavaScript.
The prototype
property of a function is not that function's prototype. It's the object that will be assigned as the prototype of objects created via new
with that function. (The name may be a bit unfortunate, though in several years I haven't come up with a better one.) The prototype of String
is Function.prototype
(because String
is a function), which we can see using ES5's getPrototypeOf
:
Object.getPrototypeOf(String) === Function.prototype // true
We can also use ES6's __proto__
property (specified for browser-based engines only, but I suspect non-browser engines will support it anyway):
String.__proto__ === Function.prototype // true
So that tells us String
is a function; but how do we know it's an Object
? Because functions are objects, so:
String.__proto__.__proto__ === Object.prototype // true
Object.getPrototypeOf(Object.getPrototypeOf(String)) === Object.prototype // true
So your .prototype.prototype
would work with .__proto__.__proto__
:
snippet.log(String.__proto__ === Function.prototype); // true
snippet.log(String.__proto__.__proto__ === Object.prototype); // true
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Or here's a multi-level hierarchy example using a non-function object:
// NOTE! Snippet requires a modern browser that has the ES6 __proto__
// property! Current Chrome, Firefox, and IE all do.
function GrandParent() {
}
function Parent() {
GrandParent.call(this);
}
Parent.prototype = Object.create(GrandParent.prototype);
Parent.prototype.constructor = Parent;
function Child() {
Parent.call(this);
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
var c = new Child();
snippet.log(c.__proto__ === Child.prototype); // true
snippet.log(c.__proto__.__proto__ === Parent.prototype); // true
snippet.log(c.__proto__.__proto__.__proto__ === GrandParent.prototype); // true
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With