数据类型
数字(number)、字符串(string)、布尔(bool)、符号(symbol)、空(undefined)、空(null)、对象(object)、bigint
number数字string字符串boolean布尔symbol符号bigint长整型undefinednullobject对象array数组function函数Date、Error等等
有以下几个需要注意的点:
- 数据类型只有 8 种哦,其中
object也被叫做引用类型或者对象类型,array和function是对象的子类型(当然还有Date、Error等等都是) string、number、boolean、null、undefined统称为原始类型(Primitive),表示不能再细分下去的基本类型;symbol是 ES6 中新增的数据类型,表示独一无二的值,通过Symbol函数调用生成,由于生成的symbol值为原始类型,所以Symbol函数不能使用new调用null和undefined通常被认为是特殊值,这两种类型的值唯一,就是其本身
因为 bigint 为 ES11 中新增的数据类型,使用较少,并且没有明显的特殊性(类型判断时没有“坑”),所以这里将其忽略
类型判断
- typeof
- instanceof
- Object.prototype.toString()
typeof
typeof 'seymoe' // 'string'
typeof true // 'boolean'
typeof 10 // 'number'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof undefined // 'undefined'
typeof {} // 'object'
typeof [] // 'object'
typeof(() => {}) // 'function'
可以看到 typeof 有以下几个问题
null得到的结果为'object'- 除了
function,其他引用类型都会返回'object'
instanceof
通过 instanceof 可以判断该实例是否是由某个类实例化而来,其原理就是测试构造函数的 prototype 是否出现在被检测对象的原型链上。
const num1 = new Number(1);
const num2 = Number(1);
const num3 = 1;
console.log(num1 instanceof Number); // true
console.log(num1 instanceof Object); // true
console.log(num2 instanceof Number); // false
console.log(num3 instanceof Number); // false
const arr = [];
const obj = {};
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true
console.log(obj instanceof Object); // true
可以看到,有几个问题:
- 对原始类型使用
instanceof,不管匹配的是啥,都是false Number其实是包装对象,继承于Object,所以由其new出来的实例,num1 instanceof Object为trueArray是由Object继承而来的,所以arr.__proto__.__proto__ === Object.prototype为true(同理,function也跟array是一样的)- 对象的
__proto__是可以自己改,譬如arr.__proto__ = Error.prototype,改了之后再用instanceof就彻底乱套了
而 instanceof 的底层实现原理如下:
/**
* 通过判断 current 的 __proto__ 链条上是否与 target.prototype 匹配
**/
function myInstanceof(current, target) {
const current = current.__proto__;
while (true) {
if (current === null) {
return false;
}
if (current === target.prototype) {
return true;
}
current = current.__proto__;
}
}
class ClassA {}
const a = new ClassA();
console.log(a.__proto__ === ClassA.prototype); // true
console.log(a instanceof ClassA); // true
class ClassB extends ClassA {}
const b = new ClassB();
console.log(b.__proto__ === ClassB.prototype); // true
console.log(b.__proto__.__proto__ === ClassA.prototype); // true
console.log(b instanceof ClassB); // true
console.log(b instanceof ClassA); // true
Object.prototype.toString()
Object.prototype.toString() 可以说是判定 JavaScript 中数据类型的终极解决方法了
Object.prototype.toString.call({}) // '[object Object]'
Object.prototype.toString.call([]) // '[object Array]'
Object.prototype.toString.call(() => {}) // '[object Function]'
Object.prototype.toString.call('seymoe') // '[object String]'
Object.prototype.toString.call(1) // '[object Number]'
Object.prototype.toString.call(true) // '[object Boolean]'
Object.prototype.toString.call(Symbol()) // '[object Symbol]'
Object.prototype.toString.call(null) // '[object Null]'
Object.prototype.toString.call(undefined) // '[object Undefined]'
Object.prototype.toString.call(new Date()) // '[object Date]'
Object.prototype.toString.call(Math) // '[object Math]'
Object.prototype.toString.call(new Set()) // '[object Set]'
Object.prototype.toString.call(new WeakSet()) // '[object WeakSet]'
Object.prototype.toString.call(new Map()) // '[object Map]'
Object.prototype.toString.call(new WeakMap()) // '[object WeakMap]'