js--浅谈instanceof的底层实现原理、手动实现一个instanceof

转自https://blog.csdn.net/qq_38722097/article/details/80717240 www.cnblogs.com/yalong/p/10…

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判断基本数据类型。 还可以通过Object.prototype.toString来判断

Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call('hi') // "[object String]"
Object.prototype.toString.call({a:'hi'}) // "[object Object]"
Object.prototype.toString.call([1,'a']) // "[object Array]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(() => {}) // "[object Function]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.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;
// 第一次判断
leftValue != rightValue
leftValue = Function.prototype.__proto__ = Object.prototype
// 第二次判断
leftValue === rightValue
// 返回 true
复制代码

Function instanceof Function 和 Function instanceof Object 的运行过程与 Object instanceof Object 类似,故不再详说。

  1. 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
复制代码
  1. 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 
复制代码
  1. Foo instanceof Function
leftValue = Foo, rightValue = Function
leftValue = Foo.__proto__ = Function.prototype
rightValue = Function.prototype
// 第一次判断
leftValue === rightValue
// 返回 true 
复制代码

模拟实现instanceof

  1. 直接使用instanceof 规则
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
    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
复制代码
  1. 在方法一的基础上使用 constructor (此方法无法用于判断继承)
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
    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
复制代码

转载于:https://juejin.im/post/5ceb8247e51d455071250a8a

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值