likes
comments
collection
share

每日五道前端面试题--day1

作者站长头像
站长
· 阅读数 12

第一天要刷的面试题如下:

  1. js中的数据类型检测方法都有哪些?
  2. 判断x为数组的方法都有哪些?
  3. null和undefined的区别是什么?
  4. typeof null的结果是什么?为什么?
  5. 手写一个函数实现instanceof操作符的功能

下面是我自己的理解:

1. js中的数据类型检测方法都有哪些?

首先,用于检测js中数据类型的方法一般来说有四种,分别为:tyepof x, x instanceof y, x.constructor?.name, Object.prototype.toString.call(x).slice(8, -1); 前两个是操作符,中间的是属性,而最后一个是方法。

  1. 先说typeof: typeof x的返回值可能为:'object' 'undefined' 'number' 'string' 'symbol' 'bigint' 'boolean' 'function'。注意它们都是首字母小写的字符串。
  • 使用typeof x 判断类型有两个问题,问题一在于:对null的判断结果是'object',这个是不正确的;第二个问题是:只能判断出对象的类型为'object',无法进一步得到更加具体的结论。
  • typeof x有一个优点那就是在判断基本类型的时候非常的方便(除了null),并且在判断'function'类型的时候也非常方便(唯一一个给出具体类型的object)。
  • 对于typeof x判断方法的缺点的处理方法就是采用更加合适的其它判别方法。
  1. x instanceof y判别方法的问题在于只对object类型生效,只能判断表达式是否成立,而不能直接告诉调用者到底是谁。其原理是通过原型链查找,所以y只要在x的原型链上都会返回true,总之这种判别法只能用来排除,因为给出的结论都是模糊性的。
  2. ?.constructor?.name这种方法对于对象类型和包装类型都生效,返回的是首字母大写的字符串。缺点在于无法分辨null和undefined,并且constructor属性值可以被篡改。不考虑其缺点的时候比typeof好用一些。
  3. 最后的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方法和原型相关的方法。

    1. Object.prototype.toString.call(x).slice(8, -1) === "Array";
    1. Array.isArray(x);
    1. x instanceof Array;
    1. x.__proto__ == Array.prototype;
    1. x.constructor.name === "Array";
    1. Array.prototype.isPrototypeof(x);

有条件的话使用第二个,后面四个实际上都是与原型有关的方法;一句话的不同说法罢了。

3. null和undefined的区别是什么?

null和undefined的区别可以通过以下四点说明:

  1. 从语义上:null表示有值,但是值为空,而undefined则表示没有值。
  2. 从语法上:形参或者变量的值为null的时候并不会触发默认值,但是如果值为undefined会强制触发默认值。
  3. typeof检测的时候,一个结果是正确的,另外一个结果不正确。
  4. 两者虽然都是基本类型,但是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。
  • 实现代码如下:
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;
}