我的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
如何回归真实?
答案 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。
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)
是的,String
是instanceof 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>