js instanceof 的工作原理细解

根据 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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值