js 数据类型判断
1. Object.prototype.toString.call()
1.1 代码
// 1. 空值 输出 "[object Undefined]"
Object.prototype.toString.call()
// 2. 字符串 输出 "[object Undefined]"
Object.prototype.toString.call(undefined)
// 3. 0 / -0 / +0 / 数字 / NaN 输出 "[object Number]"
Object.prototype.toString.call(NaN)
// 4. 字符串 输出 "[object String]"
Object.prototype.toString.call('')
// 5. null 输出 "[object Null]"
Object.prototype.toString.call(null)
// 6. [] / new Array 输出 "[object Array]"
Object.prototype.toString.call([])
let arr = new Array;
Object.prototype.toString.call(arr)
// 7. {} / new Object 输出 "[object Object]"
Object.prototype.toString.call({})
// 8. Symbol 输出 "[object Function]"
Object.prototype.toString.call(Symbol)
// 9. function 输出 "[object Function]"
Object.prototype.toString.call(function () {})
// 10. true / false / !!0 输出 "[object Boolean]"
Object.prototype.toString.call(true)
// 11. new Date 输出 "[object Date]"
let date = new Date()
Object.prototype.toString.call(date)
// 12. new Map 输出 "[object Map]"
let map = new Map()
Object.prototype.toString.call(date)
// 13. new Set 输出 "[object Set]"
let set = new Set()
Object.prototype.toString.call(set)
1.2 call() 、bind()、apply() 的用法
作用:都是用来重置 this 的指向的。
let obj = {
name: '张三',
age: 17,
myFn: function () {
console.log('我是' + this.name + ',年龄:' + this.age)
}
}
let obj2 = {
name: '李四',
age: 18
}
obj.myFn.call(obj2) // 我是李四,年龄18
obj.myFn.apply(obj2) // 我是李四,年龄18
obj.myFn.bind(obj2)() // 我是李四,年龄18
bind() 返回的是一个函数,必须调用才会被执行。
llet obj = {
name: '张三',
age: 17,
myFn: function (hobby, stature) {
console.log('我是' + this.name + ',年龄:' + this.age + ',爱好:' + hobby + ',身高:' + stature)
}
}
let obj2 = {
name: '李四',
age: 18
}
obj.myFn.call(obj2, '足球', 165); // 我是李四,年龄:18,爱好:足球,身高:165
obj.myFn.apply(obj2, ['足球', 165]); // 我是李四,年龄:18,爱好:足球,身高:165
obj.myFn.bind(obj2, '足球', 165)(); // 我是李四,年龄:18,爱好:足球,身高:165
obj.myFn.bind(obj2, ['足球', 165])(); // 我是李四,年龄:18,爱好:足球,165,身高:undefined
call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:
- call() 的参数都是直接放进去的,第二个、第三个第N个参数都是用逗号隔开obj.myFn.call(obj2, ar1,ar2,…)
- apply() 的所有参数都必须放在一个数组里面传进去obj.myFn.apply(obj2, [ar1, ar2, …])
- bind() 除了返回的是函数以外,它的参数和 call() 一样
1.3 来源于vue3 源码的各种类型的判断
// package/shared/src/index.ts
export const objectToString = Object.prototype.toString
export const toTypeString = (value: unknown): string =>
objectToString.call(value)
export const isArray = Array.isArray
export const isMap = (val: unknown): val is Map<any, any> =>
toTypeString(val) === '[object Map]'
export const isSet = (val: unknown): val is Set<any> =>
toTypeString(val) === '[object Set]'
export const isDate = (val: unknown): val is Date => val instanceof Date
export const isFunction = (val: unknown): val is Function =>
typeof val === 'function'
export const isString = (val: unknown): val is string => typeof val === 'string'
export const isSymbol = (val: unknown): val is symbol => typeof val === 'symbol'
export const isObject = (val: unknown): val is Record<any, any> =>
val !== null && typeof val === 'object'
export const isPlainObject = (val: unknown): val is object =>
toTypeString(val) === '[object Object]'
export const isPromise = <T = any>(val: unknown): val is Promise<T> => {
return isObject(val) && isFunction(val.then) && isFunction(val.catch)
}
export const isIntegerKey = (key: unknown) =>
isString(key) &&
key !== 'NaN' &&
key[0] !== '-' &&
'' + parseInt(key, 10) === key