面试_Javascript

  • JavaScript 中 call()、apply()、bind() 的用法

  var name = '小王',age=17;
  var obj = {
    name : '小张',
    objAge : this.age,
    myFun : function(fm,t){
      console.log(this.name + '年龄' + this.age , "来自" + fm + '去往' + t);
    }
  }
  
  var db = {
    name : '德玛',
    age : 99,
  }
  call 、bind 、 apply 这三个函数的第一个参数都是 this 的指向对象,第二个参数有差别
  obj.myFun.call(db,'成都','上海');  //德玛年龄99 来自成都去往上海
  obj.myFun.apply(db,['成都','上海']);//德玛年龄99 来自成都去往上海
  obj.myFun.bind(db,'成都','上海')();//德玛年龄99 来自成都去往上海
  obj.myFun.bind(db,['成都','上海'])();//德玛年龄99 来自成都,上海去往undefined
  • 谈谈对原型链的理解。

每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。

 

    function person(){
      console.log('构造函数本身');
      console.log({...this});
    }
    var ExamplesPerson = new person();//构造函数实例化
    console.log('实例原型',person.prototype);
    console.log('构造函数实例化对象',ExamplesPerson);
    console.log('实例化对象原型',ExamplesPerson.__proto__);
  • 实现防抖和节流。

防抖是什么?

用户多次点击一个按钮 , 只执行最后一次点击后的事件

 

function debounce(fn, delay = 200) {
  let timer = 0
  return function() {
    // 如果这个函数已经被触发了
    if(timer){
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      fn.apply(this, arguments); // 透传 this和参数
      timer = 0
    },delay)
  }
}

 

节流是什么?

用户多次点击只执行第一次 , 在中间的点击都不生效

 

function throttle(fn, delay = 200) {
  let  timer = 0
  return function () {
    if(timer){
      return
    }
    timer = setTimeout(() =>{
      fn.apply(this, arguments); // 透传 this和参数
      timer = 0
    },delay)
  }
}

 

区别在于 : 

防抖 : 
 if(timer){
  clearTimeout(timer)
}
节流
if(timer){
  return
}
  • 宏任务和微任务

执行顺序 :  同步代码 => 异步(微任务) => 异步(宏任务)

    console.log(1); //同步

    const promise = new Promise((resolve,reject) => { //同步
      console.log(2);
      resolve()
    })

    function fun(){
      console.log(3);
    }
    
    new fun(); //同步

    Promise.resolve().then(()=>{ //微任务
      console.log('then')
    })

    fun(); //同步

    promise.then(()=>{ //微任务
      console.log(4);
    })


    setTimeout(() => { //宏任务
      console.log(5);
    }, 0);

    console.log(6); //同步

结果 : 1 2 3 3 6 then 4 5
  • 手写Promise

 

class MYpromise {    //promise 实例
      static pending = '待定';
      static fulfilled = '成功';
      static rejected = '失败';

      constructor(fun) {
        //构造函数实例化后执行,更改status状态并运行传递进来的函数
        this.status = MYpromise.pending; //当前状态为 pending
        this.result = null;
        this.resolveCallback = [];
        this.rejectCallback = [];
        try {
          fun(this.resolve.bind(this), this.rejcet.bind(this));
        } catch (error) { //防止运行报错
          this.rejcet(error)
        }

      }

      resolve(result) {
        console.log('1.resolve执行', this.status);
        setTimeout(() => { //添加定时器 将resolve添加到事件末尾执行
          if (this.status === MYpromise.pending) {
            this.status = MYpromise.fulfilled; //更改状态为 resolve
            this.result = result; //resolve('赋值resolve传递的值')
            this.resolveCallback.forEach(callback => {//调用pending状态储存下来的函数
              callback(result);
            })
            console.log('2.resolve执行', this.status);
          }
        })
      }
      rejcet(result) {
        console.log('reject执行', this.status);
        setTimeout(() => {
          if (this.status === MYpromise.pending) {
            this.status = MYpromise.rejected; //更改状态为 reject
            this.result = result; //resolve('赋值reject传递的值')
            this.rejectCallback.forEach(callback => {
              callback(result);
            })
          }
        })
      }

      then(onFulfilled, onRejected) {
        return new MYpromise((resolve, reject) => {
          onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : () => {};
          onRejected = typeof onRejected === 'function' ? onRejected : () => {};
          console.log('then执行', this.status);

          if (this.status === MYpromise.pending) {
            console.log('then执行缓存函数', this.status);
            this.resolveCallback.push(value =>{
              const res = onFulfilled(value); //核心代码 反复执行运行.then传递进来的函数
              // console.log('onFulfilled',onFulfilled);
              // console.log(value);
              if(res instanceof MYpromise){
                res.then(resolve)
              }else{
                resolve(res);
              }
            })
           
          }

          if (this.status === MYpromise.fulfilled) {
            setTimeout(() => {
              onFulfilled(this.result)
              console.log('then执行', this.status);
            });
          }

          if (this.status === MYpromise.rejected) {
            setTimeout(() => {
              onRejected(this.result);
            });
          }

        })

      }


    }

  

    console.log('第一步'); //promise运行
    let myPromise = new MYpromise((resolve, reject) => {
      console.log('第二步');
      setTimeout(() => {
        resolve('第四步resolve成功');
        console.log('第四步')
      })
      // reject('目的失败了 函数状态更改为reject');
    })

    myPromise
      .then(res => {
          console.log(res);
          return '第五步'
        }
      )
      .then(res =>{
        console.log(res);
        return '第六步';
      })
      .then(res =>{
        console.log(res);
        return '第七步';
      }).then(res =>{
        console.log(res);
      })

    console.log('第三步')

  

      1. 执行第一步打印
      2. 构造函数实例化,运行constructor函数
        更改状态为 pending 运行实例化的时候传递进去的函数,并改变this指向为MYpromise内部 ----pending
      3. 执行第二步打印
        遇到setTimeout 异步(宏任务) , 将setTimeout加入宏任务队列 等待执行
        调用.then函数 , 此时then函数返回个自定义MYPromise构造函数并实例化
        if判断当前状态为pending 对.then传递的函数存储在数组 resolveCallback
        .then链式调用 , 有多少次.then有多少次就创建多少次 MYpromise
      4. 执行同步任务 第三步打印 至此同步任务执行完毕
      5. 开始执行宏任务队列 setTimeout
         执行resolve 遇到里面还有个setTimeout再次加入宏任务往下执行
      6. 执行第四步打印
      7. 再次运行宏任务队列 resolve里的setTimeout
         判断当前状态为 pending 更改为 fulfilled                                  ----fulfilled
         接收到 resolve 传递进来的值
         运行在 .then 的时候存储起来 传递给 .then的回调函数
         把在运行 new MYpromise 的时候 resolve 里面的参数传递给.then并运行函数
         .then函数接受到 resolve 传递的值 并打印出来
      8. 打印第四步resolve成功
         执行完毕后再次调用 resolve
      9. 再次执行当前的.then 重复 7 - 8 操作直至运行完在 MYPromise.then阶段创建的.then

 

 

posted @ 2022-09-07 16:04  啊賢  阅读(16)  评论(0编辑  收藏  举报