instanceof和typeof实现原理

instanceof 和 typeof 的实现原理

typeof实现原理

typeof一般用来判断一个变量的类型,如:number,string,object,boolean,function,undefined,symbol,bigint等类型,需要注意的是:typeof在判断非引用类型时可以清除的分辩出数据的类型,但判断引用类型时就只会返回 'object’

var a = 'test'
typeof a 
// => "string"
var b = 321
typeof b
// => "number"
var c = true
typeof c
// => "boolean"
var d = function(){}
typeof d
// => "function"
var e = Symbol()
typeof e
// => "symbol"
var f = {val:'hahh'}
typeof f
// => "object"
var g = [1,2,3]
typeof g
// => "object"
var h = BigInt(123)
typeof h
// => "bigint"

var j = new Set([1,2,3])
typeof j
// => "object"
var kkk = new Map([{val:132},{val:333}])
typeof k
// =>"object"

typeof原理
1. js底层如何存储数据的类型信息?或者说js变量中,底层如何实现变量的不同类型?
其实,js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息

000:对象
010:浮点数
100:字符串
110:布尔
1:整数

需要注意的是:, 对于undefiendnull来说,这两个信息存储有点特殊;
null: 因为null的所有机器吗都为 0;因此typeof null的结果为object
**undefiend:**用 −2^30 整数来表示;

Object.prototype.toString.call()

该方法可以用来对一个变量类型进行准确判断

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]"
Object.prototype.toString.call(NaN) // "[object Number]"
Object.prototype.toString.call(BigInt(321)) // "[object BigInt]"

instanceof 操作符的实现原理

语法: object instanceof constructor
=>object:某个实力对象;
=>constructor:某个构造函数
=>instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
instanceof:其主要作用是判断一个实例对象是否属于某种类型;注意:用于检测实例对象的类型

  let aaa = function Person(){}
  aaa instanceof Person // 左侧为需要检测的实力对象;右侧为构造函数
  => true

instanceof 也可以判断一个实例是否是其父类型或者祖先类型的实例。

let person = function () {}
let programmer = function () {}
programmer.prototype = new person() // programmer原型对象指向person的实例
let nicole = new programmer()
nicole instanceof person // true
nicole instanceof programmer // true

手动实现instanceof方法

function new_instanceof(leftVal,rightVal){
	let rightPrototype = rightVal.prototype;
	while(true){  // 持续遍历,直到有值返回;
		// 如果实例对象与构造函数的原型对象一致,返回true,表示类型一致
		if(leftVal===rightPrototype){
			return true;
		}
		// 如果实例对象为空,返回false,说明遍历到Object顶部
		if(leftVal === null){
			return false
		}
		leftVal = leftVal.__proto__; // leftVal自底向遍历获值;
	}

}

//其实 instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。
//因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype;
//如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。

几个有意思的例子:

function Foo() {
}

Object instanceof Object // true
Function instanceof Function // true
Function instanceof Object // true
Foo instanceof Foo // false
Foo instanceof Object // true
Foo instanceof Function // true

原型继承原理,见原型链图:
instanceof和typeof实现原理_第1张图片
我们知道每个 JavaScript 对象均有一个隐式的 proto 原型属性,而显式的原型属性是 prototype,只有 Object.prototype.proto 属性在未修改的情况下为 null 值。根据图上的原理,我们来梳理上面提到的几个有趣的 instanceof 使用的例子。

  • Object instanceof Object
    由图可知,Objectprototype 属性是 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 FunctionFunction instanceof Object 的运行过程与 Object instanceof Object 类似,故不再详说。

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

总结
简单来说,我们使用 typeof 来判断基本数据类型是 ok 的,不过需要注意当用 typeof 来判断 null 类型时的问题,如果想要判断一个对象的具体类型可以考虑用 instanceof,但是 instanceof 也可能判断不准确,比如一个数组,他可以被 instanceof 判断为 Object。所以我们要想比较准确的判断对象实例的类型时,可以采取 Object.prototype.toString.call 方法。

转载自:instanceof和typeof原理

你可能感兴趣的:(基础类,学习笔记,面试集)