JavaScript | 这些数据类型检测你确定会了吗?

283 阅读4分钟

0 / JS中创建值的两种方式

JS 中创建一个值有两种方案:① 字面量方式 ② 构造函数方式

注意:构造函数方式

① 不能 new Symbol/new BigInt

② 可以Object(symbol)/Object(bigint)其他数据类型值也可以,但是排除null/undefined

//=> 字面量方式
let n = 100;
let obj = {};

//=> 构造函数方式
let m = new Number(100);
let obj2 = new Object();

△ 创建值的两种方式

对于基本数据类型,两种创建方式结果是不一样的:

① 字面量方式得到的是基本数据类型,即:特殊的实例

② 而构造函数方式得到的是对象数据类型,即:正规的实例

对于引用数据类型,两种创建方式结果:除了语法上的区别,本质上是没有区别的,获取的都是对应类的实例对象

1 / JS中数据类型检测

JS中数据类型检测:

typeof value; 简单方便

Object.prototype.toString.call(value) 万全之策

prop instanceof constructor 临时当“壮丁”

constructor 临时当“壮丁”

2 / typeof

公众号:朝霞的光影笔记 ID:zhaoxiajingjing

△ 图1_typeof 判断数据类型

typeof 检测数据类型:

1、 可以有效的检测出大部分的数据类型

2、 typeof null检测的结果是object

JS设计的如此:数据值都是按照二进制存储的

1整数,010浮点数,100字符串,110布尔,000对象,-2^30undefined,000000null…………

即:typeof 检测数据类型时,按照二进制存储的值检测的,把null认为是对象了

3、 typeof 不会细分具体的对象数据类型值,所有的对象数据类型值,检测出来都是"object"

4、 typeof 检测基于构造函数创建出来的,基本数据类型的实例对象,结果也是"object"

公众号:朝霞的光影笔记 ID:zhaoxiajingjing

△ 图2_基于构造函数创建出来的基本数据类型的实例对象

3 / Object.prototype.toString.call()

Object.prototype.toString.call() 检测每个对象的类型

1、大部分内置类的原型上都有toString方法,但一般都是转为字符串,只有Object.prototype上的toString方法使用来返回当前实例对象所属的信息

"[object 所属的构造函数信息]"

2、所属的构造函数信息:是根据Symbol.toStringTag来获取的,【有,是根据它;没有,是浏览器自己计算的】

var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]

△ Object.prototype.toString

var class2type = {};
var toString = class2type.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]

△ ({}).toString

function* fn() {}
console.log(Object.prototype.toString.call(fn)); //->"[object GeneratorFunction]" 

△ 构造器函数

function Fn() {}
Fn.prototype[Symbol.toStringTag] = 'Miao~';
let f = new Fn;
console.log(Object.prototype.toString.call(f)); //=>"[object Miao~]"

△ 自定义类,指定toStringTag的值

4 / instanceof

instanceof 运算符检测构造函数的prototype属性是否出现在某个实例对象的原型链上

∴ 基于instanceof可以细分不同类型的对象,也可以检测基于构造函数方式创建的基本数据类型对象的值

但是,临时拉来当“壮丁”,有一些注意事项:

1、检测原理:构造函数[Symbol.hasInstance](实例)

2、检测原理:检测当前构造函数的原型prototype是否出现在当前实例所处的原型链上_proto_,即:只要能出现结果就为true

3、在JS中原型链是可以手动改的,检测结果不准确

4、所有的实例的原型链最后都指向了Object.prototype,即:实例 instanceof Object结果都会为true

5、字面量方式创建的基本数据类型值是无法基于instanceof检测的(浏览器不会把它转为new的方式),即:字面量创建的基本数据类型值不是对象,不存在__proto__这个东西

6、…………

var n = 100;
var m = new Number(1000);
console.log(n instanceof Number); //=> false
console.log(m instanceof Number); //=> true
console.log(m instanceof Object); //=> true

var arr = [1,2,3];
var obj = {name:'朝霞的光影笔记', id:'zhaoxiajingjing'};
console.log(arr instanceof Array); //=> true
console.log(obj instanceof Object); //=> true
console.log(arr instanceof Object); //=> true

△ 字面量和构造函数创建值

class Fn {
    static[Symbol.hasInstance](){
        console.log('miao~');
        return false;
    }
}
let f = new Fn;
console.log(f instanceof Fn);
//=>输出结果:
// miao~
// false

△ 调用:构造函数的Symbol.hasInstance

function Fn(){}
Fn.prototype = Array.prototype;
let f = new Fn;
console.log(f instanceof Array); //=> true

△ 手动修改原型指向

5 / constructor

constructor构造器,被拉来检测数据类型,也是临时抓来的“壮丁”

它的问题:可以手动被修改掉

var n = 100;
var m = new Number(1000);
console.log(n.constructor === Number); //=> true
console.log(m.constructor === Number); //=> true

var arr = [1,2,3];
var obj = {name:'朝霞的光影笔记', id:'zhaoxiajingjing'};
console.log(arr.constructor=== Array); //=> true
console.log(obj.constructor === Object); //=> true
console.log(arr.constructor === Object); //=> false

△ 通过constructor检测

function Fn(){}
Fn.prototype = {
    constructor:Array
};
let f = new Fn;
console.log(f.constructor === Fn); //=> false
console.log(f.constructor === Array); //=> true

△ 可以手动修改constructor指向

6 / 小结

JS中检测数据类型的方式4种:

1、typeof,无法区分对象数据类型值

2、Object.prototype.toString,万全之策,主要检测Symbol.toStringTag的值,没有就按浏览器计算的

3、instanceof,“壮丁”

① 检测原理:构造函数[Symbol.hasInstance]()

② 检测构造函数的prototype原型是否出现在实例对象的原型链上

=> JS的原型链是可以手动修改指向的

=> JS的原型也是可以手动修改的

③ 不能检测字面量创建的基本类型值

4、constructor,“壮丁” 可以进行手动修改指向

- end-