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:整数
需要注意的是:, 对于undefiend
和null
来说,这两个信息存储有点特殊;
null: 因为null
的所有机器吗都为 0;因此typeof null
的结果为object
;
**undefiend:**用 −2^30 整数来表示;
该方法可以用来对一个变量类型进行准确判断
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]"
语法: 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
原型继承原理,见原型链图:
我们知道每个 JavaScript 对象均有一个隐式的 proto 原型属性,而显式的原型属性是 prototype,只有 Object.prototype.proto 属性在未修改的情况下为 null 值。根据图上的原理,我们来梳理上面提到的几个有趣的 instanceof 使用的例子。
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
类似,故不再详说。
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
leftValue = Foo, rightValue = Object
leftValue = Foo.__proto__ = Function.prototype
rightValue = Object.prototype
// 第一次判断
leftValue != rightValue
leftValue = Function.prototype.__proto__ = Object.prototype
// 第二次判断
leftValue === rightValue
// 返回 true
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原理