中级面试题

面试终于告一段落,来总结一下比较有意思的面试题吧

  • 1-8这部分我认为是最难的,但也是最加分的题目,只要这些问题讲明白,面试管对你的看法会有大大的提升

1. 可以实现一个 bind 函数么?

Function.prototype.myBind = function(thisArg) {
  /* 有人经常会将这一步防御式判断省略,但这里也是一个考点
  * 什么情况下 this 的指向不是一个 'function' ?
  */ 
  if (typeof this !== 'function') return;
  var _self = this
  var args = Array.prototype.slice.call(arguments, 1)
  var fnNop = function () {} // 定义一个空函数
  var fnBound = function () {
    // 这里是另一个考点,this 的指向问题,还有使用 instanceof 判断的理由
    var _this = this instanceof _self ? this : thisArg

    return _self.apply(_this, args.concat(Array.prototype.slice.call(arguments)))
  }
  // 维护原型关系
  if (this.prototype) {
    fnNop.prototype = this.prototype;
  }

  fnBound.prototype = new fnNop();

  return fnBound;
}

这道题其实包含的东西特别多,需要好好理解从函数定义、函数执行、函数的原型、this 的指向等,所以我将这道题放到第一位,务必好好理解。

2、有没有使用过 async 和 await ,了解其中的原理么,如何优雅的统一处理错误?

原理的话大家好好看看阮老师的书就好了,上面介绍的很详细。
如何优雅的处理,我认为在这篇博客中,会有很大的收获:https://juejin.im/post/5c49eb28f265da613a545a4b

3、有没有使用过 Promise , 可以实现一个 Promise.all 么?

  • 首先你需要了解一下 Promise.all 做了什么
    1、接收一个 Promise 实例的数组或具有 Iterator 接口的对象
    2、如果元素不是 Promise 对象,则使用 Promise.resolve 转成 Promise 对象
    3、如果全部成功,状态变为 resolved,返回值将组成一个数组传给回调
    4、只要有一个失败,状态就变为 rejected,返回值将直接传递给回调
    all() 的返回值也是新的 Promise 对象

直接上一段代码(别人的)

function promiseAll(promises) {
  return new Promise(function(resolve, reject) {
  // 防御式判断必须要有
    if (!isArray(promises)) {
      return reject(new TypeError('arguments must be an array'));
    }
    var resolvedCounter = 0;
    var promiseNum = promises.length;
    var resolvedValues = new Array(promiseNum);
    // 根据传入的数组长度,循环
    for (var i = 0; i < promiseNum; i++) {
      (function(i) {
        Promise.resolve(promises[i]).then(function(value) {
          resolvedCounter++
          resolvedValues[i] = value
          if (resolvedCounter == promiseNum) {
            return resolve(resolvedValues)
          }
        }, function(reason) {
          return reject(reason)
        })
      })(i)
    }
  })
}

4、在平常开发中,我们对于一个负责的对象,想获取其中的一个值,经常会写一些 a && a.b && a.b.c ,但是我们只想获取其中的一个值啊,写一个函数实现当前需求

  • 首先最简单的思路就是切割,循环
function path (obj,path) {
  let res = null;
  let aPath = path.split('.');
  aPath.foreach((sPath) => {
    if(sPath in obj){
      res = obj[sPath];
      obj = obj[sPath];
    }
  })
  return res;
}

高阶一点,可以看下 lodash 中的 get 函数

5、有了解过函数式编程么?说一下你了解的纯函数

  • 本人比较菜,这道题答的并不是很好,只说出了固定的输入有固定的输出
    具体可以参考:https://llh911001.gitbooks.io/mostly-adequate-guide-chinese/content/

6、了解EventLoop么,简述一下

  • 这道题能说的多细就多细,比较加分

7、数组的去重

  • 不多做解释了,这个题目的答案太多了,看下别人总结的吧
    https://segmentfault.com/a/1190000016418021

8、instanceof 可以正确判断对象的原理是什么?

  • 其实 instanceof主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。

9、可以在不新添加变量的情况下,对于一个数组进行排序么?

  • 这是排序中的堆排序,可以背一下

10、vue 中 scope 的实现原理

  • 其实就是通过 PostCss 给对应的节点添加了一个data属性,通过 css 属性选择器来控制

11、观察者模式与订阅发布模式是一样的么?

  • 本人傻傻的回答了一样的,结果....
    但是事实上,确实不一样,难受啊

  • 在观察者模式中,观察者是知道 Subject 的,Subject 一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。

  • 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。

  • 观察者模式大多数时候是同步的,比如当事件触发,Subject 就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。

  • 观察者 模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式

注:此文档会持续更新,一场面试就是一场学习,愿大家都有一个好的归宿

你可能感兴趣的:(中级面试题)