js instanceof 的工作原理细解
程序员文章站
2022-07-13 21:10:53
...
根据 MDN 的解释
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
s instanceof F 用递归函数来表达, 流程大致如下:
function _instanceof(s, F) {
if(s.__proto__ === F.prototype) {
// 找到目标
return true
} else if("__proto__" in F) {
// 存在上一层原型1
_instanceof(s, F.__proto__)
} else {
// 穷尽原型链仍找不到目标
return false
}
}
_instanceof(s, F)
instanceof 的工作原理就是将 s 每一层的 __proto__ 与 F.prototype 做比较
找到相同返回 true
至最后一层仍没有找到返回 false
因为构造函数的 prototype 可以修改(一般不建议这么做), 所以 instanceof 返回的结果并不是固定的, 甚至是错误的
我们通过下例理解其原因
<html>
<head>
<title>instanceof 的工作原理</title>
</head>
<body>
<script type="text/javascript">
function section1() {
function F1() { }
function F2() { }
// F1.prototype 的粗略结构
// F1_prototype = {
// constructor: F1,
// __proto__: {
// constructor: Object
// }
// }
// F2.prototype 的粗略结构
// F2_prototype = {
// constructor: F2,
// __proto__: {
// constructor: Object
// }
// }
var s = new F1();
// 根据实例化原理可知 s.__proto__ === F1.prototype
console.log(s.__proto__ === F1.prototype) // true
// 所以得以下结果
console.log(s instanceof F1) // true
// 根据 F2_prototype 显示的结构, s 整个原型链都没有 F2.prototype
// 所以得以下结果
console.log(s instanceof F2) // false
}
function section2() {
function F1() { }
// F1.prototype 的粗略结构
// F1_prototype = {
// constructor: F1,
// __proto__: {
// constructor: Object
// }
// }
var s = new F1();
// s 的粗略结构
// _s = {
// __proto__: {
// constructor: F1,
// __proto__: {
// constructor: Object
// }
// }
// }
// *提示: {} 相当于新建一个对象, 与其它对象都不相等, 类似于 {} !== {}
F1.prototype = {};
// F1.prototype 的粗略结构
// F1_prototype = {
// __proto__: {
// constructor: Object
// }
// }
var s2 = new F1();
// s2 的粗略结构
// _s2 = {
// __proto__: {
// __proto__: {
// constructor: Object
// }
// }
// }
// F1.prototype 重写后, F1.prototype 是一个新的对象, 不存在于 s 的原型链上
// 所以得以下结果
console.log(s instanceof F1) // false
// 根据 F1_prototype, _s2 显示的结构
console.log(s2.__proto__ === F1.prototype) // false
// 所以得以下结果
console.log(s2 instanceof F1) // true
}
function section3() {
function F1() { }
function F2() { }
// F2.prototype 的粗略结构
// F2_prototype = {
// constructor: F2,
// __proto__: {
// constructor: Object
// }
// }
var s = new F2();
// 根据实例化原理可知 s.__proto__ === F2.prototype
console.log(s.__proto__ === F2.prototype) // true
// 所以得以下结果
console.log(s instanceof F2) // true
// 根据 F2_prototype 显示的结构, s 整个原型链都没有 F1.prototype
// 所以得以下结果
console.log(s instanceof F1) // false
}
function section4() {
function F1() { }
function F2() { }
F2.prototype = new F1(); // 继承
// F1.prototype 的粗略结构
// F1_prototype = {
// constructor: F1,
// __proto__: {
// constructor: Object
// }
// }
// F2.prototype 的粗略结构
// *提示: F2.prototype.__proto__ === F1.prototype
// F2_prototype = {
// constructor: undefined,
// __proto__: {
// constructor: F1,
// __proto__: {
// constructor: Object
// }
// }
// }
var s = new F2();
// 根据实例化原理可知 s.__proto__ === F2.prototype
console.log(s.__proto__ === F2.prototype) // true
// 所以得以下结果
console.log(s instanceof F2) // true
// 根据 F2_prototype 显示的结构, 推理可得
console.log(s.__proto__.__proto__ === F1.prototype)
// 所以得以下结果
console.log(s instanceof F1) // true
}
function section5() {
function F1() { }
function F2() { }
F2.prototype = F1.prototype; // 继承
// F1.prototype 的粗略结构
// F1_prototype = {
// constructor: F1,
// __proto__: {
// constructor: Object
// }
// }
// F2.prototype 的粗略结构
// F2_prototype = {
// constructor: F1,
// __proto__: {
// constructor: Object
// }
// }
var s = new F2();
// 根据实例化原理可知 s.__proto__ === F2.prototype
console.log(s.__proto__ === F2.prototype) // true
// 所以得以下结果
console.log(s instanceof F2) // true
// 因为 F2.prototype 重写后就是 F1.prototype
console.log(s.__proto__ === F1.prototype)
// 所以得以下结果
console.log(s instanceof F1) // true
}
section1()
section2()
section3()
section4()
section5()
</script>
</body>
</html>
因为 instanceof 是通过构造函数的原型(prototype) 计算结果的, 所以当 prototype 被修改后, instanceof 的结果也将受到影响
//end
上一篇: docker、k8s基础:mysql容器化部署,挂载data到宿主机
下一篇: 第七章 图(一)