(String instanceof Object)返回true但我无法在String.prototype链中找到Object.prototype

时间:2015-04-22 08:10:03

标签: javascript prototype instanceof

我的JavaScript说instanceof运算符搜索构造函数中是否存在prototype属性。

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

这仅仅意味着String.prototype链上不存在Object.prototype。 哪个让我困惑,那么String instanceof Object如何回归真实?

2 个答案:

答案 0 :(得分:4)

你的JavaScript不是骗你的:D。确实instanceof运算符测试了构造函数的prototype属性是否存在于Object原型链上。

您只是错过了函数在JavaScript中具有双重生命的事实。它们同时也是功能和对象。当您测试以下代码时

String instanceof Object; // true

上面代码中的

String实际上是您所指的对象。现在让我们运行以下验证:

String.__proto__ === Object.prototype; //假

String.__proto__.__proto__ === Object.prototype; //真

那就是你要找的'true' :)这反映了String proto链上存在Object.prototype。

注意:“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.

您可以尝试遍历原型链并避免 proto 的另一种方法如下:

Object.getPrototypeOf(String.prototype) === Object.prototype;

希望这会有所帮助。快乐的JavaScript。

答案 1 :(得分:3)

是的,Stringinstanceof Object,因为String是一个函数,函数是JavaScript中的对象。

函数的prototype属性该函数的原型。 将被分配作为通过new使用该函数创建的对象原型的对象。 (这个名字可能有点不幸,虽然几年后我还没有找到更好的名字。)String的原型是Function.prototype(因为String是一个函数) ,我们可以看到使用ES5的getPrototypeOf

Object.getPrototypeOf(String) === Function.prototype // true

我们也可以使用ES6的__proto__属性(仅限基于浏览器的引擎,但我怀疑非浏览器引擎会支持它):

String.__proto__ === Function.prototype // true

这告诉我们String是一个函数;但我们怎么知道它是Object?因为函数是对象,所以:

String.__proto__.__proto__ === Object.prototype // true
Object.getPrototypeOf(Object.getPrototypeOf(String)) === Object.prototype // true

因此,.prototype.prototype适用于.__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>

或者这是使用非功能对象的多级层次结构示例:

// 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>