返回的结果都是字符串
缺点:不能细分对象
基本数据类型 :除null以外均可返回正确结果
引用数据类型:除function以外一律返回object类型
null返回object类型
function返回function类型
检测未被声明的变量 undefined
那么为什么检测null却返回了object类型呢??
原理
js在底层存储变量的时候会按照计算机存储的二进制进行检测
000 对象
010浮点数
100 字符串
110布尔
1 整数
null 00000,,,
-2^30 undefined
type of在判断null的时候由于null所有的机器码均为0,因此被当做了对象来看待
let n = 100;
console.log(typeof n);//"number"
console.log(typeof typeof n);//typeof "number"--->"string"
console.log(typeof null);//object
let fn = function fn() {
}
console.log(typeof fn);//function
a = "hello"
console.log(typeof a);//string
console.log(typeof [10, 20]);//"object"
应用:
临时用来检测数据类型 本意:检测当前的实例是否属于这个类
instanceof 能细分对象(通过原型链,万物皆对象)
缺点:
原理
传统版本
按照原型链进行检测(只要当前检测的构造函数[它的原型对象] 出现在实例的原型链上,则检测的结果是true),沿着原理链一直查找直到object.prototype都没有就是false
let arr = [10, 20];
console.log(arr instanceof Array);//true
console.log(arr instanceof Object);//true
console.log(arr instanceof Date);//false
let n = 10;//基础类型
console.log(n instanceof Number);//false
新版本
在Function.prototype上有一个Symbol.hasInstance属性方法(所有函数都可以使用),当我们基于 “[对象] instanceof [构造函数]”检测处理的时候,内部是这样处理的:
[构造函数][Symbol.hasInstance]([对象])
class Fn {
name = 'Fn';
x = 10;
y = 20;
sum() {
if (!this.name) throw new TypeError('this.name is not defined');
// ...
}
// 只要基于ES6中的class创建类,基于“static xxx”这种语法重写Symbol.hasInstance才有用;如果是ES5创建的类,基于 Fn[Symbol.hasInstance]=xxx 这样重写是无效的!!
static[Symbol.hasInstance](obj) {
return (obj.name && Object.getPrototypeOf(obj) === Fn.prototype) ? true : false;
}
}
let f1 = new Fn;
let f2 = new Fn;
console.log(f1 instanceof Fn); //true
f1.sum();
let obj = {};
Object.setPrototypeOf(obj, Fn.prototype);
console.log(obj instanceof Fn); //Fn[Symbol.hasInstance](obj) false
console.log(obj instanceof Fn); //true
obj.sum(); //报错
原型链的指向可以随意改动 导致检测不准确
function Fn() {
}
Fn.prototype = Array.prototype;
let f = new Fn();
console.log(f instanceof Array);//true
constructor 指回构造函数
作用:
let arr = [10, 20];
console.log(arr.constructor === Array);//true
console.log(arr.constructor === Object);//false
缺点 原型重定向也会影响 constructor 的判断
下面案例中把fn 的原型重定向了 新的原型对象中没有了 constructor 它会根据原型链找到object
function Fn(){
}
Fn.prototype={};
let f=new Fn();
console.log(f.constructor===Fn);//false
console.log(f.constructor===Object);//true
Object.prototype.toString.call 是js中唯一一个检测数据类型最完美的
大部分内置类的原型上都有tostring方法一般都是转为字符串的,但是object.prototype.tostring是检测数据类型的 返回值中包含了自己的构造函数信息 返回的结果 “[object ?]”
?是啥值
let arr = [10, 20, 30];
console.log(Object.prototype.toString.call(arr));//[object Array]
console.log(Object.prototype.toString.call(10));//[object Number]
重写内置instanceof
// 重写内置instanceof
var instance_of = function instance_of(obj, Ctor) {
// 右侧必须是一个函数
if (typeof Ctor !== "function") throw new TypeError("Right-hand side of 'instanceof' is not callable");
// 原始值检测都是false
if (obj == null || !/^(object|function)$/.test(typeof obj)) return false;
// 构造函数必须具备prototype
if (!Ctor.prototype) throw new TypeError("Function has non-object prototype 'undefined' in instanceof check");
// 支持Symbol.hasInstance的使用这个方法处理
if (typeof Symbol !== "undefined") return Ctor[Symbol.hasInstance](obj);
// 不支持:自己按照原型链查找
let proto = Object.getPrototypeOf(obj);
while (proto) {
if (proto === Ctor.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
return false;
};
let arr = [10, 20];
console.log(instance_of(arr, Array)); //true
console.log(instance_of(arr, RegExp)); //false
console.log(instance_of(arr, Object)); //true
1. typeof 二进制 不能细分对象
2. instanceof 临时 能细分对象(通过原型链,万物皆对象)
缺点:不能检测基础类型(false),检测不准确(原型链可以修改)
直接(es6)修改[Symbol.hasInstance]---》检测不准确
3. constructor 临时 (查看值是哪个构造函数)能细分对象--->比instanceof更精准
缺点:检测不准确,可以修改
4.最完美的 Object.prototype.toString.call()
------------------------------------------------完结-----------------------------------------------------------------
-----------------------------------------------接受大佬们的批改和指点,欢迎留言--------------------------------