以下题目来自掘金等其它博客,但是问题的答案都是根据笔者自己的理解做出的。如果你最近想要换工作或者巩固一下自己的前端知识基础,不妨和我一起参与到每日刷题的过程中来,如何?
第一天要刷的面试题如下:
- js中的数据类型检测方法都有哪些?
- 判断x为数组的方法都有哪些?
- null和undefined的区别是什么?
- typeof null的结果是什么?为什么?
- 手写一个函数实现instanceof操作符的功能
下面是我自己的理解:
1. js中的数据类型检测方法都有哪些?
首先,用于检测js中数据类型的方法一般来说有四种,分别为:tyepof x
, x instanceof y
, x.constructor?.name
, Object.prototype.toString.call(x).slice(8, -1)
; 前两个是操作符,中间的是属性,而最后一个是方法。
- 先说typeof: typeof x的返回值可能为:
'object' 'undefined' 'number' 'string' 'symbol' 'bigint' 'boolean' 'function'
。注意它们都是首字母小写的字符串。
- 使用typeof x 判断类型有两个问题,问题一在于:对null的判断结果是'object',这个是不正确的;第二个问题是:只能判断出对象的类型为'object',无法进一步得到更加具体的结论。
- typeof x有一个优点那就是在判断基本类型的时候非常的方便(除了null),并且在判断'function'类型的时候也非常方便(唯一一个给出具体类型的object)。
- 对于typeof x判断方法的缺点的处理方法就是采用更加合适的其它判别方法。
- x instanceof y判别方法的问题在于只对object类型生效,只能判断表达式是否成立,而不能直接告诉调用者到底是谁。其原理是通过原型链查找,所以y只要在x的原型链上都会返回true,总之这种判别法只能用来排除,因为给出的结论都是模糊性的。
- ?.constructor?.name这种方法对于对象类型和包装类型都生效,返回的是首字母大写的字符串。缺点在于无法分辨null和undefined,并且constructor属性值可以被篡改。不考虑其缺点的时候比typeof好用一些。
- 最后的Object.prototype.toString.call(x).slice(8, -1)方法是王炸,是唯一一种能够判断出null数据类型的方法。返回值为首字母大写的字符串,列举其可能的返回值:
'String' 'Null' 'Undefined' 'Number' 'String' 'Symbol' 'Bigint' 'Boolean' 'Array' 'Date' 'RegExp' 'Error' 'Function'
。可惜这个方法还是有缺点的const a = {};
a可以通过修改[Symbol.toStringTag]
的值改变此方法的返回值。
总结下来,这四个方法各有各的用武之地,但是如果想要清晰的知道x的类型的话,推荐使用最后一种方式。
2. 判断x为数组的方法都有哪些?
总结下来就是:toString方法,ES6方法和原型相关的方法。
-
Object.prototype.toString.call(x).slice(8, -1) === "Array";
-
Array.isArray(x);
-
x instanceof Array;
-
x.__proto__ == Array.prototype;
-
x.constructor.name === "Array";
-
Array.prototype.isPrototypeof(x);
有条件的话使用第二个,后面四个实际上都是与原型有关的方法;一句话的不同说法罢了。
3. null和undefined的区别是什么?
null和undefined的区别可以通过以下四点说明:
- 从语义上:null表示有值,但是值为空,而undefined则表示没有值。
- 从语法上:形参或者变量的值为null的时候并不会触发默认值,但是如果值为undefined会强制触发默认值。
- typeof检测的时候,一个结果是正确的,另外一个结果不正确。
- 两者虽然都是基本类型,但是undefined不是保留字,这意味着你可以为其赋值,或者声明其为变量,这是不安全的,所以一般使用void 0作为undefined的替代。
4. typeof null的结果是什么?为什么?
- 计算结果为:"object",之所以出现这个结果,源自js这门编程语言设计之初的规定。
- 在js第一版的时候,所有的数据都是存放在一个32bit的存储空间中,这32bit被划分成两个部分,一个是用来表示类型的,通常占0-3个bit,剩下的部分则都是用来表示数据的。
- 为什么是0-3个bit位表示类型呢?因为当时表示int类型的是1,没错只有一位,所以对于整数来说剩下的31位都可以用来表示数据;而对于string类型,标识符则为100,有三个bit位;double类型的是010;boolean则为110;而object的类型则是用000三个bit位进行表示;
- 除了上面这些,undefined用一个溢出的整数来表示,所以它没有标识位,为0位;而对于null,js简单粗暴的使用机器码NULL,但是机器码NULL本身是32个0。
- 注意32个0意味着前三位也是0,所以typeof null的时候null会被当成object,所以结果返回的是'object'。
5. 手写一个函数实现instanceof操作符的功能
- x instanceof y 的作用原理就是,在x的原型链上寻找y,如果找到了就返回true,如果找不到就返回false;
- 根据其作用原理,其实现过程也就呼之欲出了:首先判断x是不是object类型的,如果不是直接返回false就可以了。如果是的话,则逐级比较x的原型和y是否相等,知道x原型链的尽头,也就是null。如果此时y与任何一层原型都不相等,则返回false,否则返回true。
- 实现代码如下:
javascript
function myInstanceof(obj, cons){
if(Object(obj)!==obj) return false;
let _p = obj.__proto__;
while(_p!==null){
if(_p==cons.prototype) return true;
_p = _p.__proto__;
}
return false;
}