Open
Description
一、语法
1.1 基本用法
object instanceof constructorFunc
判断构造函数constructorFunc
的prototype
属性是否在对象object
的原型链上。
Object.create({}) instanceof Object // true
Object.create(null) instanceof Object // false
Function instanceof Object // true
Function instanceof Function // true
Object instanceof Object // true
1. 作为类型判断的一种方式,instanceof
操作符不会对object
进行隐式类型转换
"" instanceof String; // false,基本类型不会转成对象
new String('') instanceof String; // true
- 对于没有原型的对象,或则基本类型直接返回
false
1 instanceof Object // false
Object.create(null) instanceof Object // false
2. constructorFunc
必须是函数,且可以作为构造函数(即要具有prototype
属性)
// TypeError: Right-hand side of 'instanceof' is not callable
1 instanceof ({})
// TypeError: Function has non-object prototype 'undefined' in instanceof check
({}) instanceof (() => {})
3. 对于跨全局执行上下文intanceof
就不能正常工作了
不同的全局执行上下文的对象和函数都是不相等的。
<!DOCTYPE html>
<html>
<head></head>
<body>
<iframe src=""></iframe>
<script type="text/javascript">
var iframe = window.frames[0];
var iframeArr = new iframe.Array();
console.log([] instanceof iframe.Array) // false
console.log(iframeArr instanceof Array) // false
console.log(iframeArr instanceof iframe.Array) // true
</script>
</body>
</html>
1.2 PK Object.prototype.isPrototypeOf()
Object.prototype.isPrototypeOf()
用于判断对象是否在另一个对象的原型链上。
[] instanceof Array
相等于Array.prototype.isPrototypeOf([])
看似可以利用Object.prototype.isPrototypeOf()
代替instanceof
,但是其实不是的见下面“自定义instanceof
行为”。
综上:只是instanceof
内部逻辑利(OrdinaryHasInstance
)和Object.prototype.isPrototypeOf()
存在相似的地方。
二、instanceof check
var foo = () => {}
var a = {}
// TypeError: Function has non-object prototype 'undefined' in instanceof check
a instanceof foo
// 显示增加个`prototype `成员函数(必须是函数)就不报错了
foo.prototype = function() {}
a instanceof foo // false
要弄清原因还是看下规范InstanceofOperator :
- If Type(target) is not Object, throw a TypeError exception.
- Let instOfHandler be ? GetMethod(target, @@hasInstance).
- If instOfHandler is not undefined, then
- Return ! ToBoolean(? Call(instOfHandler, target, « V »)).
- If IsCallable(target) is false, throw a TypeError exception.
- Return ? OrdinaryHasInstance(target, V).
即:
- 如果
constructorFunc
不是对象,直接抛TypeError
异常; - 如果
constructorFunc
定义了Symbol.hasInstance
方法(不为undefined
就算),则调用该方法,并以该方法的返回值作为instanceof
的值;
var foo = () => {}
var a = {}
// 显示增加个`prototype `成员函数(必须是函数)就不报错了
foo.prototype = function() {}
// 自定义Symbol.hasInstance方法
Object.defineProperty(foo, Symbol.hasInstance, {
value: {} // 不是个方法
});
// TypeError: object is not a function
a instanceof foo
- 否则走
OrdinaryHasInstance(target, V)
流程。
三、自定义instanceof
行为
instanceof
操作符默认通过原型链判断(OrdinaryHasInstance
),但可以利用Symbol.hasInstance
自定义instanceof
行为。
var foo = () => {}
var a = {}
// 显示增加个`prototype `成员函数(必须是函数)就不报错了
foo.prototype = function() {}
// 自定义Symbol.hasInstance方法
Object.defineProperty(foo, Symbol.hasInstance, {
value: function(instance) {
return true
}
});
a instanceof foo // true
所有函数(包含不可以作为构造函数的函数,如Function.prototype
)都定义了Symbol.hasInstance
方法。
function foo() {
}
typeof foo[Symbol.hasInstance]() // "function"
typeof Function.prototype[Symbol.hasInstance] // "function"
四、利用Object.getPrototypeOf
实现instanceof
function isInstanceOf(obj, constructor) {
if(typeof constructor !== 'object') {
throw new TypeError('constructor is not a object')
}
// Symbol.hasInstance方式
if(constructor[Symbol.hasInstance] !== undefined) {
return !!constructor[Symbol.hasInstance](obj);
}
// 原型链方式:
if(typeof obj !== 'object') {
return false
}
if(typeof constructor !== 'function') {
throw new TypeError('constructor is not a function')
}
if(typeof constructor.prototype !== 'object') {
throw new TypeError('Function has non-object prototype');
}
while(obj !== null) {
if(obj === constructor.prototype) {
return true;
}
obj = Object.getPrototypeOf(obj);
}
return false;
}