js面试题

148 阅读3分钟

判断数据类型

  • typeof 判断除 null 以外的基础类型
  • instanceof 判断引用类型
  • Object.prototype.toaString.call()判断所有类型 instanceof 原理
function instanceof(L, O) {
  L = L.__proto__;
  O = O.prototype;
  while(true){
    if(L===null)return false;
    if(L===O){
      return true;}
      else{
        L=L.__proto__
      }
}

apply, call, bind 区别

三者都是用来改变 this 的指向,this 被指定为传入函数的第一个参数。 bind 是返回新的函数以便稍后调用,call、apply 是立即调用函数。 call: 第二个参数是参数列表。 apply: 第二个参数是一个数组或类数组的对象。

事件循环

Javascript是单线程,基于事件循环

js事件分为同步任务和异步任务,遇到异步任务分类为宏任务(macro-task)和微任务(micro-task)。

  • 宏任务:包括整体代码script,setTimeout,setInterval
  • 微任务:Promise.then,process.nextTick(node中)

事件的执行过程: 1、遇到同步任务,进入调用栈,立即执行 2、遇到异步任务,异步任务有了结果后,宏任务和微任务分别进入不同的事件队列 3、同步任务执行完后,先检查微任务队列,进入调用栈执行 4、微任务队列清空后,执行宏任务队列,依次进入调用栈执行


// 这是一个同步任务
console.log('1')            --------> 直接被执行
                                      目前打印结果为:1

// 这是一个宏任务
setTimeout(function () {    --------> 整体的setTimeout被放进宏任务列表
  console.log('2')                    目前宏任务列表记为【s2】
});

new Promise(function (resolve) {
  // 这里是同步任务
  console.log('3');         --------> 直接被执行
  resolve();                          目前打印结果为:13
  // then是一个微任务
}).then(function () {       --------> 整体的then[包含里面的setTimeout]被放进微任务列表
  console.log('4')                    目前微任务列表记为【t45】
  setTimeout(function () {
    console.log('5')
  });
});

浏览器瞅了一眼微任务列表 发现里面有微任务 就开始全部执行
then(function () {
  console.log('4')            --------> 直接被执行
                                        目前打印结果为:134
  setTimeout(function () {    --------> 被放进宏任务列表了
    console.log('5')                    目前宏任务列表记为【s2、s5】
  });
});


浏览器发现微任务执行完毕了

开始执行宏任务列表

setTimeout(function () {
  console.log('2')   --------> 直接被执行
                               目前打印结果为:1342

});

setTimeout(function () {
  console.log('5')   --------> 直接被执行
                               目前打印顺序为: 134255
});

最终结果为: 13425

Promise

1、promise是一个容器,保存某个异步操作的结果,这个结果决定promise当前是什么状态,promise有三种状态,pending,fulfilled,rejected,并且只有两种可能,pending=>fulfilled,pending=>rejected

2、promise通过then方法给异步操作结果添加事件回调,有两种情况,

一是先获得了异步操作结果,后添加事件回调,会立即执行 二是先添加了回调,会保存在一个回调数组里面,等异步操作结果返回了执行

问题1

有一个非常长的链式调用, 怎么让它在某一个函数中停下来,为什么可以这样做

let promise = new Promise(function(resolve, reject){
  resolve('第一次成功')
})
promise.then(function(val) {
 //第一种方法
  throw new error()
 // 第二种方法
 return Promise.reject()
}).then(function(val) {
  console.log('被跳过的方法')
}).catch(function(val) {
  console.log('返回失败')
})