Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(String instanceof Object) returns true but I am not able to find the Object.prototype in String.prototype chain

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?

like image 872
invincibleDudess Avatar asked Mar 16 '23 08:03

invincibleDudess


2 Answers

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.

like image 145
dopeddude Avatar answered Apr 28 '23 12:04

dopeddude


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>
like image 34
T.J. Crowder Avatar answered Apr 28 '23 13:04

T.J. Crowder