This is due to an odd behavior in Chrome dev tools. The (now deprecated) __proto__
property is a getter/accessor property, which means when it is accessed, it runs a portion of code. That portion of code looks something like so:
Object.getPrototypeOf(this); // which returns this[[Prototype]]
The this
in the above example is typically the object that you call .__proto__
on. For example, if you did arr.__proto__
, then this
would be arr
, so we end up getting the prototype of the arr
array as expected. In the Chrome dev tools console, things are a little different. Rather than the getter being invoked on an object like arr
, it is instead invoked manually when you press (...)
:

So now the question is - what is the value of this
when performing Object.getPrototypeOf(this);
inside of the __proto__
getter when it is invoked manually in the Chrome dev tools rather than invoking it via property access such as arr.__proto__
? This is up to the Chrome dev tools team to decide, but it seems like the way that it behaves is that it sets the this
to the originally logged object1. In your second example, that object is arr.__proto__
. As a result, the getter ends up showing the prototype of arr.__proto__
again, rather than null
.
The below code snippet (see Chrome console output), is a simple example of this behavior in action:
const obj = Object.create({
get nested() {
console.log("obj === this:", this === obj); // true
console.log("obj[[Prototype]] === this:", this === Object.getPrototypeOf(obj)); // false
return this;
}
}, {
foo: {
value: 'bar',
enumerable: true
}
});
// View chrome console for output
console.log(obj);
In the above example, a new object is created with the property {foo: "bar"}
which has a prototype set to an object with a getter called nested() {}
. This getter returns and logs the value of this
. When the above code is run in Chrome, and the getter is invoked by clicking (...)
on obj[[Prototype]]
(ie: obj.__proto__
) nested
property, you get the following output:

In the above, the two red boxes represent the same object, showing that this
inside of the getter doesn't refer to the prototype object (ie: {nested: (...)}
) when it is invoked using (...)
, but rather it refers to the originally logged object. Unlike this, when you use arr.__proto__.__proto__
, the object logged is Object.prototype
, so when you invoked the __proto__
getter, the this
refers to the object Object.prototype
, which returns null
when its prototype is accessed.
To properly walk the prototype chain, you can use nested calls to Object.getPrototypeOf()
:
Object.getPrototypeOf(Object.getPrototypeOf(Object.getPrototypeOf(arr))); // null
1 This is just an assumption based on some observations, but might not be correct - I'm not entirely sure how chrome decides what to set the this
to, but the important thing to note is that it isn't always the immediate object that the getter property appears in.