第1问:js中的数据类型有哪些?
1.1 原始数据类型:共有7种
Boolean Number String undefined null Bigint Symbol
1.2 引用数据类型:1种
Object对象(包括普通Object、Function、Array、Date、RegExp、Math)
第2问:你真的懂typeof吗?
2.1 typeof的作用?
区分数据类型返回7种数据类型:number、string、boolean、undefined、object、function,以及ES6新增的symbol
2.2 typeof能正确区分数据类型吗?
不能。对于原始类型,除null都可以正确判断;对于引用类型,除function外,都会返回"object"
2.3 typeof注意事项
typeof返回值为·格式,注意类似这种考题: typeof(typeof(undefined)) -> "string"
typeof未定义的变量不会报错,返回"undefiend"
typeof(null) -> "object": 遗留已久的bug
typeof无法区别数组与普通对象: typeof([]) -> "object"
typeof(NaN) -> "number"
常见变量的数据类型:
console.log(typeof(b));// b未定义,返回undefined
console.log(typeof(undefined)); // undefined
console.log(typeof(NaN)); // NaN 为number类型
console.log(typeof(null)); // object
var a = '123abc';
console.log(typeof(+a)); // +a 类型转换为NaN
console.log(typeof(!!a)); // boolean
console.log(typeof(a + "")); // string
console.log(typeof(typeof(null)));// string
console.log(typeof(typeof({})));// string
第3问:什么是instanceof?你能模拟实现一个instanceof吗?
3.1 instanceof可以准确判断对象的类型,其内部机制是判断对象的原型链上是否存在该类型的原型。
instanceof常用来判断A是否为B的实例:
// A是B的实例,返回true,否则返回false
// 判断A的原型链上是否有B的原型
A instanceofB
3.2 模拟实现instanceof
思想:沿原型链往上查找
function instance_of(Case, Constructor) {
// 基本数据类型返回false
// 兼容一下函数对象
if ((typeof(Case) !== 'object' && typeof(Case) !== 'function') || Case === 'null') return false;
let CaseProto = Object.getPrototypeOf(Case);
while (true) {
// 查到原型链顶端,仍未查到,返回false
if (CaseProto == null) return false;
// 找到相同的原型
if (CaseProto === Constructor.prototype) return true;
CaseProto = Object.getPrototypeOf(CaseProto);
}
}
测试:
console.log(instance_of(Array, Object)) // true
function User(name){
this.name = name;
}
const user = new User('zc');
const vipUser = Object.create(user);
console.log(instance_of(vipUser, User)) // true
第4问:如何区分数组与对象?instanceof判断是否是数组可靠吗?
4.1 Array.isArray()
如果不存在Array.isArray()呢?可以借助Object.prototype.toString.call()实现,这种实现方式兼容性最好
if (!Array.isArray) {
Array.isArray = function(o) {
return typeof(o) === 'object'
&& Object.prototype.toString.call(o) === '[object Array]';
}
}
4.2 instanceof判断
判断方式
arr instanceof Array // 如果为true,则arr为数组
instanceof判断数组如此之简单,为何不推荐使用那?
instanceof操作符的问题在于,如果网页中存在多个iframe,那便会存在多个Array构造函数,此时判断是否是数组会存在问题。
第五问:如何判断一个数是否为NaN?
5.1 NaN有个非常特殊的特性,NaN与任何值都不相等,包括它自身
NaN === NaN // false
鉴于这个独特的特性,可以手撕一个比较简单的判断函数
function isNaN(x) {
return x != x;
}
5.2 isNaN方法:不推荐使用。MDN对它的介绍是:isNaN函数内包含一些非常有趣的规则。
isNaN的有趣机制:会先判断参数是不是Number类型,如果不是Number类型会尝试将这个参数转换为Number类型,之后再去判断是不是NaN。
举个例子:
// 是不是很有趣
console.log(isNaN([])) // false
console.log(isNaN([1])) // false
console.log(isNaN([1, 2])) // true
console.log(isNaN(null)) // false
console.log(isNaN(undefined)) // true
isNaN的结果很大程度上取决于Number()类型转换,后面会专门有一部分来介绍。
5.3 Number.isNaN(推荐使用)
与isNaN()相比,Number.isNaN()不会自行将参数转换成数字,只有在参数是值为NaN的数字时,才会返回 true。
第6问:如何实现一个可靠的类型判断函数
利用Object.prototype.toString.call([value]),可以精准判断数据类型,大家可以根据这个原理封装一个自己的type方法。
toString.call(()=>{}) // [object Function]
toString.call({}) // [object Object]
toString.call([]) // [object Array]
toString.call('') // [object String]
toString.call(22) // [object Number]
toString.call(undefined) // [object undefined]
toString.call(null) // [object null]
toString.call(new Date) // [object Date]
toString.call(Math) // [object Math]
toString.call(window) // [object Window]