typeof 和 instanceof

typeof

typeof一般被用于判断一个变量的类型,我们可以利用 typeof来判断number, string, object, boolean, function, undefined, symbol这七种类型。

let s = new String('abc');
typeof s === 'object' // true
s instanceof String  // true

typeof 的原理

js 在底层是怎么存储数据的类型信息呢?或者说,一个js的变量,在它的底层实现中,它的类型信息是怎么实现的呢?

js 在底层存储变量的时候,会在变量的机器码的低位1-3位存储其类型信息。

  • 000:对象
  • 010:浮点数
  • 100:字符串
  • 110:布尔
  • 1:整数
  • null:所有机器码均为0
  • undefined:用−2^30整数来表示

所以,typeof 在判断 null的时候就出现问题了,由于null 的所有机器码均为0,因此直接被当做了对象来看待。

然而用instanceof来判断的话:

null instanceof null  // TypeError: Right-hand side of 'instanceof' is not an object

null直接被判断为不是object,这也是 JavaScript 的历史遗留bug

判断类型的方法:Object.prototype.toString

一个不错的判断类型的方法,就是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]"

普通对象与函数对象

JavaScript 中,万物皆对象!(Function.prototype.__proto__ === Object.prototype)但对象也是有区别的。分为普通对象和函数对象,ObjectFunctionJS自带的函数对象。原文

var o1 = {}; 
var o2 = new Object();
var o3 = new f1();

function f1(){}; 
var f2 = function(){};
var f3 = new Function('str','console.log(str)');

console.log(typeof Object); //function 
console.log(typeof Function); //function  

console.log(typeof f1); //function 
console.log(typeof f2); //function 
console.log(typeof f3); //function   

console.log(typeof o1); //object 
console.log(typeof o2); //object 
console.log(typeof o3); //object

在上面的例子中 o1 o2 o3 为普通对象,f1 f2 f3 为函数对象。怎么区分,其实很简单,凡是通过new Function()创建的对象都是函数对象,其他的都是普通对象。f1,f2,归根结底都是通过 new Function()的方式进行创建的。

Function Object也都是通过 New Function()创建的。

原型对象

JavaScript中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。

其中每个函数对象都有一个prototype 属性。在chromefirefox中,每个对象都有_ _proto_ _属性,指向的原型对象。

同时,在默认情况下,所有的原型对象都会自动获得一个 constructor(构造函数)属性,这个属性(是一个指针)指向 prototype属性所在的函数。(构造函数)

Person.prototype.constructor == Person
person1.constructor == Person
Person.prototype.constructor == Person

在 Person 创建的时候,创建了一个它的实例对象并赋值给它的 prototype。

原型对象(Person.prototype)是 构造函数(Person)的一个实例。

function Person() {};
 console.log(Person.prototype) //Person{}
 console.log(typeof Person.prototype) //Object
 console.log(typeof Function.prototype) // Function,这个特殊
 console.log(typeof Object.prototype) // Object
 console.log(typeof Function.prototype.prototype) //undefined

上文提到凡是通过 new Function( )产生的对象都是函数对象。因为 A 是函数对象,所以Function.prototype 是函数对象。

 var A = new Function ();
 Function.prototype = A;

Object.prototype.__proto__ === null

函数对象

所有函数对象的_ _proto_ _都指向Function.prototype,它是一个空函数。(Empty function

Number.__proto__ === Function.prototype  // true
Number.constructor == Function //true

Boolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //true

String.__proto__ === Function.prototype  // true
String.constructor == Function //true

所有的构造器都来自于Function.prototype,甚至包括根构造器ObjectFunction自身。

// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Object.__proto__ === Function.prototype  // true
Object.constructor == Function // true

// 所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身
Function.__proto__ === Function.prototype // true
Function.constructor == Function //true

Array.__proto__ === Function.prototype   // true
Array.constructor == Function //true

RegExp.__proto__ === Function.prototype  // true
RegExp.constructor == Function //true

Error.__proto__ === Function.prototype   // true
Error.constructor == Function //true

Date.__proto__ === Function.prototype    // true
Date.constructor == Function //true

MathJSON是以对象形式存在的,无需new。它们的_ _proto_ _Object.prototype

Math.__proto__ === Object.prototype  // true
Math.construrctor == Object // true

JSON.__proto__ === Object.prototype  // true
JSON.construrctor == Object //true

instanceof

typeof在检测object类型的时候,总是会返回object,所以js提供了另外一个接口来实现对对象类型的判断,那就是我们的instanceof

instanceof复杂用法

function Foo() {};
console.log(Object instanceof Object); // true

左边的Object_ _proto_ _指向Function.prototypeFunction.prototype指向Object.prototype

console.log(Function instanceof Object); // true

左边的Function_ _proto_ _指向Function.prototype,而Function.prototype__proto_ _指向Object.prototype,所以返回true

console.log(Function instanceof Function); // true
console.log(Number instanceof Number); // false
console.log(String instanceof String); // false
console.log(Foo instanceof Function); // true
console.log(Foo instanceof Foo); // false

instanceof操作符的机制

function  instance_of (L, R){
    var O = R.prototype;    //右边表达式的显示原型
    var L = L._proto_;  //左边的表达式的隐式原型
    //从原型链向上寻找
    while(true){
        if(L === null){
            return false;
        };
        if(O === L){
            return true;
        };
        L = L._proto_;
    }
}

参考文章

https://juejin.im/post/5b0b9b9051882515773ae714
https://juejin.im/post/59cbc479518825790e5cb581
https://www.jianshu.com/p/dee9f8b14771

你可能感兴趣的:(typeof 和 instanceof)