js--浅谈instanceof的底层实现原理、⼿动实现⼀个instanceof typeof 实现原理
typeof⼀般被⽤于判断⼀个变量的类型,我们可以利⽤typeof来判断number、string、object、boolean、function、undefined、symbol这七种类型。当判断不是object时其它都好说。、
typeof 不存在的变量 = “undefined”
typeof 对象 = “object”
typeof null = "object"
typeof 数组 = “object”
typeod ⽅法的实例(⽐如 new Array()) =“object”
js在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息
000:对象
010:浮点数
100: 字符串
110:布尔值
1: 整数
但是,对于undefined和null来说,这两个的信息存储⽐较特殊。 null所有机器码均为0,undefined为-2^30整数,所以typeof判断时null均为0,因此被当做对象。 所以⼀般⽤typeof判断基本数据类型。 还可以通过String来判断
String.call(1) // "[object Number]"
String.call('hi') // "[object String]"
String.call({a:'hi'}) // "[object Object]"
String.call([1,'a']) // "[object Array]"
String.call(true) // "[object Boolean]"
String.call(() => {}) // "[object Function]"
String.call(null) // "[object Null]"
String.call(undefined) // "[object Undefined]"
String.call(Symbol(1)) // "[object Symbol]"
复制代码
instanceof 操作符的实现原理
instanceof主要作⽤就是判断⼀个实例是否属于某种类型
let person = function(){
}
let no = new person()
no instanceof person//true
复制代码
原理⼤概如下
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__
}
}
复制代码
其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查的过程中会遍历左边变量的原型链,直到到右边变量的 prototype,如果查失败,则会返回 false,告诉我们左边变量并⾮是右边变量的实例。
同时还要了解js的原型继承原理
我们知道每个 JavaScript 对象均有⼀个隐式的 proto 原型属性,⽽显式的原型属性是 prototype,只有 Object.prototype.proto 属性在未修改的情况下为 null 值。根据图上的原理,我们来梳理上⾯提到的⼏个有趣的 instanceof 使⽤的例⼦。
1. 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;
// 第⼀次判断
typeof arrayleftValue != rightValue
leftValue = Function.prototype.__proto__ = Object.prototype
// 第⼆次判断
leftValue === rightValue
// 返回 true
复制代码
Function instanceof Function 和 Function instanceof Object 的运⾏过程与 Object instanceof Object 类似,故不再详说。
2. 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
复制代码
3. 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
复制代码
4. Foo instanceof Function
leftValue = Foo, rightValue = Function
leftValue = Foo.__proto__ = Function.prototype rightValue = Function.prototype
// 第⼀次判断
leftValue === rightValue
// 返回 true
复制代码
模拟实现instanceof
1. 直接使⽤instanceof 规则
var O = R.prototype;
L = L.__proto__;
while (true) {
if (L === null)
return false;
if (O === L) // 这⾥重点:当 O 严格等于 L 时,返回true
return true;
L = L.__proto__;
}
}
// 开始测试
var a = []
var b = {}
function Foo(){}
var c = new Foo()
function child(){}
function father(){}
child.prototype = new father()
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
复制代码
2. 在⽅法⼀的基础上使⽤ constructor (此⽅法⽆法⽤于判断继承)
var O = R;
L = L.__proto__;
while (true) {
if (L === null)
return false;
if (O === L.constructor) // 这⾥重点:当 O 严格等于 L 时,返回 true return true;
L = L.__proto__;
}
}
// 开始测试
var a = []
var b = {}
function Foo(){}
var c = new Foo()
function child(){}
function father(){}
child.prototype = new father()
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)) // false 这⾥就是⽆法⽤于判断继承的console.log(instance_of(d, father)) // true
复制代码
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论