有趣的面试题系列(一)

1.使用setTimeout实现setInterval的功能

转载自:https://blog.csdn.net/jameszhufu/article/details/81774431

timeFuction();

function timeFunction(){
    
    var timer = setTimeOut(function(){
        timeFuction();
        clearTimeOut(timer)
    },2000);
}

2.EventLoop问题

console.log('script start');

async function async1(){
    await async2();
    console.log('async1 end');
}

async function async2(){
    console.log('async2 end');
}

async1();

setTimeout(function(){
    console.log('setTimeout');
},0)

new Promise(resolve=>{
    console.log('Promise');
    resolve();
}).then(function(){
    console.log('promise1')
}).then(function(){
    console.log('promise2')
})

console.log('script end')

执行结果:

  1. scirpt start
  2. async2 end
  3. Promise
  4. script end
  5. promise1
  6. promise2
  7. async1 end
  8. setTimeout  

详解

首先先来解释下上述代码的 async 和 await 的执行顺序。当我们调用 async1 函数时,会马上输出 async2 end,并且函数返回一个 Promise,接下来在遇到 await的时候会就让出线程开始执行 async1 外的代码,所以我们完全可以把 await 看成是让出线程的标志。

然后当同步代码全部执行完毕以后,就会去执行所有的异步代码,那么又会回到 await 的位置执行返回的 Promise 的 resolve 函数,这又会把 resolve 丢到微任务队列中,接下来去执行 then 中的回调,当两个 then 中的回调全部执行完毕以后,又会回到 await 的位置处理返回值,这时候你可以看成是 Promise.resolve(返回值).then(),然后 await 后的代码全部被包裹进了 then 的回调中,所以 console.log('async1 end') 会优先执行于 setTimeout。
————————————————
版权声明:本文为CSDN博主「itKingOne」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/itKingOne/article/details/86502910

3.React setState  异步操作

class Example extends React.Component {
  constructor() {
    super();
    this.state = {
      val: 0
    };
  }
  
  componentDidMount() {
    this.setState({val: this.state.val + 1});
    console.log(this.state.val);    // 第 1 次 log

    this.setState({val: this.state.val + 1});
    console.log(this.state.val);    // 第 2 次 log

    setTimeout(() => {
      this.setState({val: this.state.val + 1});
      console.log(this.state.val);  // 第 3 次 log

      this.setState({val: this.state.val + 1});
      console.log(this.state.val);  // 第 4 次 log
    }, 0);
  }

  render() {
    return null;
  }
};

执行结果: 0, 0, 2, 3。

总结起来就是这样:

  • this.setState首先会把state推入pendingState队列中
  • 然后将组件标记为dirty
  • React中有事务的概念,最常见的就是更新事务,如果不在事务中,则会开启一次新的更新事务,更新事务执行的操作就是把组件标记为dirty。
  • 判断是否处于batch update
  • 是的话,保存组建于dirtyComponent中,在事务结束的时候才会通过 ReactUpdates.flushBatchedUpdates 方法将所有的临时 state merge 并计算出最新的 props 及 state,然后将其批量执行,最后再关闭结束事务。
  • 不是的话,直接开启一次新的更新事务,在标记为dirty之后,直接开始更新组件。因此当setState执行完毕后,组件就更新完毕了,所以会造成定时器同步更新的情况。

转载地址:https://www.jianshu.com/p/b38a7a4eda2b

4.手写 防抖 和节流函数

//  防抖 : 限制一段时间内不触发
function 防抖(fn,t){
    var timer=null;
    return function(){
        var context=this;
        var args = arguments;
        if(timer) clearTimeout(timer);
        timer=setTimeout(function(){
            fn.apply(context,args);
            clearTimeout(timer);
            timer=null;
        },t)
    }
}

//  节流 : 限制一段时间内触发次数
function 节流(fn,t){
    var timer=null;
    return function(){
        var context=this;
        var args = argument;
        if(timer) return;
        timer=setTimeOut(function(){
            fn.apply(context,args);
            clearTimeOut(timer);
            timer=null;
        },t)
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天又懒得加班

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值