typeof:能判断所有值类型,函数。不可对 null、对象、数组进行精确判断,因为都返回 object 。
console.log(typeof undefined); // undefined console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof "str"); // string
console.log(typeof Symbol("foo")); // symbol console.log(typeof 2172141653n); // bigint console.log(typeof function () {}); // function // 不能判别
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof null); // object
instanceof:能判断对象类型,不能判断基本数据类型,其内部运行机制是判断在其原型链中能否找到该类型的原型。比如考虑以下代码:
class People {}
class Student extends People {}
const vortesnail = new Student();
console.log(vortesnail instanceof People); // true
console.log(vortesnail instanceof Student); // true
原理
function myInstanceOf(left,right){ //获取对象的原型
let proto=Object.getPrototypeOf(left) //获取构造函数的prototype对象
let prototype=right.prototype //判断构造函数的prototype对象是否在对象的原型链上
while(true){
if(!proto) return false;
if(proto==prototype) return true; //如果没有找到,就继续起原型链找Object.getPrototypeOf(proto)
proto=Object.getPrototypeOf(proto) }
}
constructor有两个作用,一是判断数据的类型,二是通过对象实例通过constructor对象访问它的构造函数,需要如果创建一个对象来改变它的原型,constructor就不能判断了
改变原型了
console.log((2).constructor===Number);//true console.log(function(){}).constructor===Array//true
//function Fn(){}
Fn.prototype=new Array()
var f=new Fn();
console.log(f.constructor===Fn)//false
console.log(f.constructor===Array)//true
Object.prototype.toString.call():所有原始数据类型都是能判断的,还有 Error 对象,Date 对象等。
Object.prototype.toString.call(2); // "[object Number]"
Object.prototype.toString.call(""); // "[object String]"
Object.prototype.toString.call(true); // "[object Boolean]"
Object.prototype.toString.call(undefined); // "[object Undefined]"
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(Math); // "[object Math]"
Object.prototype.toString.call({}); // "[object Object]"
Object.prototype.toString.call([]); // "[object Array]"
Object.prototype.toString.call(function () {}); // "[object Function]"
言简意赅的说:所有数据类型都是对象的一种类型,而### Object.prototype.toString可以返回当前调用者的对象类型。 找到原型上面有个toString()方法、 在Object.prototype上的toString()方法,可以说是最原始的toString()方法了,其他类型都或多或少重写了toString()方法,导致不同类型的对象调用toString()方法产生返回值各不相同。
Object.prototype.toString.call()为什么要加call()
因为Object.prototype.toString()返回的是调用者的类型。不论你toString()本身的入参写的是什么,在Object.prototype.toString()中,他的调用者永远都是Object.prototype;所以,在不加call()情况下,我们的出来的结果永远都是 '[object Object]'
Object.prototype.toString.call()为什么要在原型找
有些小伙伴可以回疑惑了。为什么一定要用Object.prototype.toString.call()这个方法,那么长,写起来很麻烦,我直接在当前数据本身去调用toString(),然后让他顺着原型链去找,最后找到Object.prototype.toString这个方法不行吗?连call都省下了。
还真不行。
因为,每个数据类,他们都重写了toString()方法。所以,如果我们拿数据本身去toString(),是得不到对象类型的。