4种检测数据类型的方法
* 1. typeof xxx
* => typeof null => "object"
* => typeof 数组、正则、日期、对象 => "object"
*
* 2. xxx instanceof xxx
* 检测当前实例是否属于这个类(也可以用来检测数据类型:对typeof的补充)
* => 不能用来处理基本数据类型(基本数据类型基于构造函数方式创建的实例是可以的)
* => 只要出现在实例的原型链上的类,检测结果都是TRUE(页面中可以手动更改原型链的指向,这样导致检测结果不一定准确)【MDN:instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上】
*
* 3. xxx.constructor === xxx
* => constructor也是一样可以被更改的(这个检测结果也不一定准确)
* => 基本数据类型也可以处理
*
* 4. Object.prototype.toString:其它类的原型上的toString基本上都是转换为字符串的,只有Object原型上的是检测数据类型的 返回结果 "[object 所属的类]"
* => Object.prototype.toString执行,它中的this是谁,就是检测谁的数据类型
* => Object.prototype.toString.call(xxx)
* => ({}).toString.call(xxx)
* => 最强大的检测数据类型方法(基本上没有弊端)
let arr = [];
let reg = /^$/;
console.log(arr instanceof Array); // => true
console.log(reg instanceof Array); // => false
console.log(1 instanceof Number); // => false
console.log(new Number(1) instanceof Number); // => true
console.log(Symbol() instanceof Symbol); // => false
console.log(arr instanceof Object); // => true
function Fn() { }
Fn.prototype = Array.prototype;
let f = new Fn;
console.log(f instanceof Array); // => true
自己封装检测数据类型的方法
// 补充的代码
let aa = "[object Object]"
let bb = "[object Number]"
let res = aa.split(' ') // ["[object", "Object]"]
let res2 = bb.split(' ') // ["[object", "Number]"]
console.log(res2)
let second1 = res[1] // Object]
let second2 = res2[1] // Number]
console.log(second1, second2)
console.log(second1.slice(0, -1), second2.slice(0, -1)) // Object Number
// 我的方案
function toType(obj) {
let type = Object.prototype.toString.call(obj)
return type.split(' ')[1].slice(0, -1).toLowerCase()
}
// 编写toType方法,实现数据类型检测
function toType(obj) {
let type = Object.prototype.toString.call(obj);
return /^[object ([a-z]+)]$/i.exec(type)[1].toLowerCase();
}
console.log(toType(1)); // => "number"
console.log(toType(NaN)); // => "number"
console.log(toType([])); // => "array"
console.log(toType(/^d+$/)); // => "regexp"
console.log(toType({})); // => "object"
console.log(toType(Symbol('aa'))); // => "symbol"
console.log(toType(BigInt(10))); // => "bigint"
第一个是大正则捕获的,第二个是小正则捕获的
* 创建一个变量值两种方式
* 1.字面量
* 2.构造函数
* 对于基本类型来说,第一种方式创建的是 值类型,第二种方式创建的是 引用类型,但是不论哪一种类型都是当前类的一个实例。
* 把一个对象转换为字符串、数字:
1.先调用其valueOf这个方法,如果返回了对应的原始值(值类型), 接下来会基于原始值进行相关的操作
2.如果没有对应的原始值,才去调用toString
3.Number、String、Boolean、Symbol、BigInt这些类的原型上都有自己的valueOf方法,可以获取原始值[[PrimitiveValue]]
4.基本上数据类型的类的原型上都有自己的toString,但是只有基本类型所属类的原型上才有valueOf,引用类型只有Object的原型上才有valueOf(Date比较特殊,它的原型上也有valueOf)
let obj1 = {};
let obj2 = new Object();
let arr1 = [10];
let arr2 = new Array(10);
let n1 = 10;
let n2 = new Number(10);
console.log(n2 + 10); // => 20
let arr = [10];
console.log(arr + 10); // => "1010"
// 补充:对象转Number,Number函数
const obj = {
valueOf() {
// return 'aaa'
// return [11, 22]
return {name: '哈哈'}
},
toString() {
return 33
}
}
console.log(obj.valueOf())
console.log(obj.toString())
// 返回基本数据类型,则结果是NaN,说明此时不会去调用toString;返回引用类型,则结果是33,说明此时会去调用toString
console.log(Number(obj))