你真的了解 instanceof 吗?
使用 instanceof 就是判断一个实例是否属于某种类型。更准确的说,instanceof 可以在继承关系中用来判断一个实例是否属于它的父类型或者祖先类型的实例。
null instanceof null; // TypeError: Right-hand side of 'instanceof' is not an object
null 直接被判断为不是 object,这也是 JavaScript 的历史遗留 bug。
实现原理
function myInstanceof(leftValue, rightValue) {
rightValue = rightValue.prototype; // 取右表达式的 prototype 值
leftValue = leftValue.__proto__; // 取左表达式的__proto__值
while(true) {
if(leftValue === null) return false;
if(leftValue === rightValue) return true;
leftValue = leftValue.__proto__;
}
}
其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。
注意到:
function Foo() {
}
Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
Foo instanceof Foo // false
Foo instanceof Object // true
Foo instanceof Function // true
可以发现:Object 和 Function instanceof 自身等于 true,而其他类 instanceof 自己却又不等于 true。
我们需要知道每个 JavaScript 对象均有一个隐式的 __proto__
原型属性,而显式的原型属性是 prototype,只有 Object.prototype.__proto__
属性在未修改的情况下值为 null 。
Object instanceof Object
Object 的 prototype 属性是 Object.prototype, 而由于 Object 本身是一个函数,由 Function 所创建,所以 Object.__proto__
的值是 Function.prototype,而 Function.prototype 的 __proto__
属性是 Object.prototype,所以我们可以判断出,Object instanceof Object 的结果是 true 。
leftValue = Object.__proto__ = Function.prototype;
rightValue = Object.prototype;
// 第一次判断
leftValue != rightValue
leftValue = Function.prototype.__proto__ = Object.prototype
// 第二次判断
leftValue === rightValue
// 返回 true
Function instanceof Function 和 Function instanceof Object 的运行过程与 Object instanceof Object 类似。
Foo instanceof Foo
Foo 函数的 prototype 属性是 Foo.prototype,而 Foo 的 proto 属性是 Function.prototype。Foo 的原型链上并没有 Foo.prototype ,因此 Foo instanceof Foo 也就返回 false 。
leftValue = Foo, rightValue = Foo
leftValue = Foo.__proto = Function.prototype
rightValue = Foo.prototype
// 第一次判断
leftValue != rightValue
leftValue = Function.prototype.__proto__ = Object.prototype
// 第二次判断
leftValue != rightValue
leftValue = Object.prototype = null
// 第三次判断
leftValue === null
// 返回 false
Foo instanceof Object
leftValue = Foo, rightValue = Object
leftValue = Foo.__proto__ = Function.prototype
rightValue = Object.prototype
// 第一次判断
leftValue != rightValue
leftValue = Function.prototype.__proto__ = Object.prototype
// 第二次判断
leftValue === rightValue
// 返回 true
Foo instanceof Function
leftValue = Foo, rightValue = Function
leftValue = Foo.__proto__ = Function.prototype
rightValue = Function.prototype
// 第一次判断
leftValue === rightValue
// 返回 true
主要是一个理解原型链的过程。
所以我们要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call()
方法。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: JavaScript 合并排序数组
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论