js--淺談instanceof的底層實現原理、手動實現一個instanceof

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

typeof 實現原理

typeof通常被用於判斷一個變量的類型,咱們能夠利用typeof來判斷number、string、object、boolean、function、undefined、symbol這七種類型。當判斷不是object時其它都好說。、數組

typeof 不存在的變量 = 「undefined」bash

typeof 對象 = 「object」函數

typeof null = "object"測試

typeof 數組 = 「object」ui

typeod 方法的實例(好比 new Array()) =「object」spa

js在底層存儲變量的時候,會在變量的機器碼的低位1-3位存儲其類型信息.net

  • 000:對象
  • 010:浮點數
  • 100: 字符串
  • 110:布爾值
  • 1: 整數

可是,對於undefined和null來講,這兩個的信息存儲比較特殊。 null全部機器碼均爲0,undefined爲-2^30整數,因此typeof判斷時null均爲0,所以被當作對象。 因此通常用typeof判斷基本數據類型。 還能夠經過Object.prototype.toString來判斷prototype

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主要做用就是判斷一個實例是否屬於某種類型code

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
複製代碼
相關文章
相關標籤/搜索