一、instanceOf
insatanceOf运算符用于检测构造函数是否在某个实例的原型链上。
function application() {
this.name = 'Kerry';
}
const app = new application();
app instanceof application; // true
app.__proto__ === application.prototype; // true
二、instanceOf原理
1.原型继承原理
在了解instanceOf运算符实现的原理前,先了解一下JavaScript中原型的继承原理。我们知道JavaScript的每一个实例对象,都有其内置隐式的原型属性__proto__,该对象通过__proto__指向其构造函数的原型对象(prototype),该构造函数也是一个对象,因此也有其内置的__proto__属性指向更上一层对象的原型对象,只有Object.prototype.__proto__属性在未修改的情况下为null值,null值没有原型对象,因此null为原型链的末端。通过__proto__所串联起来的每一个对象,构成了原型链。
function application() { }
const app = new application();
app.__proto__ === application.prototype; // true
application.prototype.__proto__ === Object.prototype; // true
app.name = 'Kerry'; // 在app的自身定义属性name
application.prototype.age = '21'; // 在app的原型上定义属性age
Object.prototype.hobby = 'Game'; // 在app的原型的原型上定义属性hobby
console.log(app.name); // 实例对象app在自身属性中找到name
console.log(app.age); // 实例对象app通过app.__proto__.age在原型中找到属性age
console.log(app.hobby); // 实例对象app通过application.prototype.__proto__在原型的原型中找到属性hobby
原型链如下:app ——> application.prototype ——> Object.prototype ——> null
2.instanceOf原理
function new_instance_of(leftVaule, rightVaule) {
let rightProto = rightVaule.prototype; // 取右表达式的 prototype 值
leftVaule = leftVaule.__proto__; // 取左表达式的__proto__值
while (true) {
if (leftVaule === null) {
return false;
}
if (leftVaule === rightProto) {
return true;
}
leftVaule = leftVaule.__proto__ // 遍历左表达式的原型链
}
}
function application() { }
const app = new application();
new_instance_of(app, application); // true
new_instance_of(app, Object); // true
由此可见,instanceOf的原理就是不断遍历左边变量的原型链,并不断判断右边变量是否在左边变量的原型链上,如果查找失败,则返回false,意为左边变量不是右边变量的实例对象。
三、手动实现
function instance_of(L, R) {
var O = R.prototype;
L = L.__proto__;
while (true) {
if (L === null)
return false;
if (O === L)
return true;
L = L.__proto__;
}
}
// 开始测试
var a = []
var b = {}
function Foo() { }
function child() { }
function father() { }
child.prototype = new father() // child.prototype.__proto__ === father.prototype
var c = new Foo()
var d = new child()
console.log(instance_of(a, Array)) // true
console.log(instance_of(b, Object)) // true
console.log(instance_of(b, Array)) // false
console.log(instance_of(a, Object)) // true
console.log(instance_of(c, Foo)) // true
console.log(instance_of(d, child)) // true
console.log(instance_of(d, father)) // true