typeof
typeof 是一元操作符,放在其单个操作数的前面,操作数可以是任意类型。返回值为表示操作数类型的一个字符串。
typeof功能范围
typeof可以正确判断除了null之外的所有基本类型,而对于引用类型,除了函数外其他都会被判断为object。
typeof null // 'object'
typeof undefined; // "undefined"
typeof false; // "boolean"
typeof 1; // "number"
typeof '1'; // "string"
typeof {}; // "object"
typeof []; // "object"
typeof new Date(); // "object"
typeof Symbol(); // "Symbol"
typeof 123n // 'bigint'
typeof原理
不同的对象在底层都表示为二进制,在Javascript中二进制前(低)三位存储其类型信息。
instanceof
通俗一些讲,instanceof 用来比较一个对象是否为某一个构造函数的实例。注意,instanceof运算符只能用于对象,不适用原始类型的值。
instanceof功能范围
instanceof无法判断基本类型,但可以正确判断引用类型。
// 输出 false
console.log('菲菲' instanceof String)
// 输出 true
console.log(new Date() instanceof Date)
instanceof原理
object instanceof constructor :检测 constructor.prototype是否存在于参数 object的 原型链上。
手写instanceof
/**
自定义instanceof
*/
function instanceOf(left, right) {
let proto = left.__proto__
while(proto){
if(proto === right.prototype){
return true
}
proto = proto.__proto__
}
return false
}
class A{}
class B extends A {}
class C{}
const b = new B()
// 输出 true
console.log(instanceOf(b,B))
// 输出 true
console.log(instanceOf(b,A))
// 输出 false
console.log(instanceOf(b,C))
Object.prototype.toString
// 以下是11种:
var number = 1; // [object Number]
var string = '123'; // [object String]
var boolean = true; // [object Boolean]
var und = undefined; // [object Undefined]
var nul = null; // [object Null]
var obj = {a: 1} // [object Object]
var array = [1, 2, 3]; // [object Array]
var date = new Date(); // [object Date]
var error = new Error(); // [object Error]
var reg = /a/g; // [object RegExp]
var func = function a(){}; // [object Function]
function checkType() {
for (var i = 0; i < arguments.length; i++) {
console.log(Object.prototype.toString.call(arguments[i]))
}
}
checkType(number, string, boolean, und, nul, obj, array, date, error, reg, func)
除了以上 11 种之外,还有:
console.log(Object.prototype.toString.call(Math)); // [object Math]
console.log(Object.prototype.toString.call(JSON)); // [object JSON]
除了以上 13 种之外,还有:
function a() {
console.log(Object.prototype.toString.call(arguments)); // [object Arguments]
}
a();
所以我们可以识别至少 14 种类型,当然我们也可以算出来,[[class]] 属性至少有 12 个。
根据对象的constructor属性判断
constructor 判断方法跟instanceof相似,但是constructor检测Object与instanceof不一样,constructor还可以处理基本数据类型的检测,不仅仅是对象类型。
constructor属性,可以得知某个实例对象,到底是哪一个构造函数产生的。
constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错。所以,修改原型对象时,一般要同时修改constructor属性的指向。
console.log('22'.constructor === String) // true
console.log(true.constructor === Boolean) // true
console.log([].constructor === Array) // true
console.log(document.constructor === HTMLDocument) // true
console.log(window.constructor === Window) // true
console.log(new Number(22).constructor === Number) // true
console.log(new Function().constructor === Function) // true
console.log((new Date()).constructor === Date) // true
console.log(new RegExp().constructor === RegExp) // true
console.log(new Error().constructor === Error) // true
注意:
1.null和undefined没有constructor;
2.判断数字时使用(),比如 (123).constructor,如果写成123.constructor会报错
3.constructor在类继承时会出错,因为Object被覆盖掉了,检测结果就不对了
//注意当出现继承的时候,使用constructor会出现问题
function A() {};
function B() {};
A.prototype = new B(); //A继承自B
console.log(A.constructor === B) -------->false
var C = new A();
//现在开始判断C是否跟A的构造器一样
console.log(C.constructor === B) -------->true
console.log(C.constructor === A) -------->false
//解决这种情况,通常是手动调整对象的constructor指向
C.constructor = A; //将自己的类赋值给对象的constructor属性
console.log(C.constructor === A); -------->true
console.log(C.constructor === B); -------->false