• js 手撕代码高频面试题


    js 手撕代码高频面试题

    1、debounce(防抖)

    触发高频时间后n秒内函数只会执行一次,如果n秒内高频时间再次触发,则重新计算时间。

    const debounce = (fn, time) => {
      let timeout = null;
      console.log('我来了') // 我来了
      return function() {
        // console.log('--aa--', timeout)
        clearTimeout(timeout)  // timeout是定时器一个数字标识
        // console.log(timeout,'--bb--', clearTimeout(timeout))
        timeout = setTimeout(() => {
          // console.log('过了3秒我才执行哦,中间有操作会被清0,重新被计时')
          fn.apply(this, arguments);
        }, time);
        // console.log('--cc--', timeout)
      }
    };

    防抖常应用于用户进行搜索输入节约请求资源,window触发resize事件时进行防抖只触发一次。

    使用

    function A(){
      console.log('每隔3秒执行一次的函数中间有操作会被清0,重新被计时---test', new Date())
      // console.log('test')
    }
    var testDebounce = debounce(A, 3000)
    
    // window.onresize = function(){
    //   testDebounce()
    // }
    window.onresize = testDebounce 
    timeout是定时器一个数字标识

    每隔三秒执行一次,中间有操作会请0重新计时,也就是设定的时间就是执行最短时间

    2、throttle(节流)

    高频时间触发,但n秒内只会执行一次,所以节流会稀释函数的执行频率。
    节流常应用于鼠标不断点击触发、监听滚动事件。
    const throttle = (fn, time) => {
      let flag = true;
      return function() {
        if (!flag) return;
        flag = false;
        setTimeout(() => {
          fn.apply(this, arguments);
          flag = true;
        }, time);
      }
    }
    window.onload = (event) => {
      console.log('page is fully loaded');
      let btn2 = document.getElementById("myBtn2")
      const throFn = throttle(testFn, 2000)
       btn2.addEventListener('click', throFn, false) 
     
    };
    
    <button id="myBtn2">节流点击</button>

    3、 模拟一个new 运算符

    3.1  第一种实现方式

    new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。

    function Car(make, model, year) {
      this.make = make;
      this.model = model;
      this.year = year;
    }
    
    const car1 = new Car('Eagle', 'Talon TSi', 1993);
    
    console.log(car1.make);
    // expected output: "Eagle"

    语法

    new constructor[([arguments])]

    参数

    constructor一个指定对象实例的类型的类或函数。

    arguments

    一个用于被 constructor 调用的参数列表。

    描述
    new 关键字会进行如下的操作:

    创建一个空的简单JavaScript对象(即{});
    为步骤1新创建的对象添加属性__proto__,将该属性链接至构造函数的原型对象 ;
    将步骤1新创建的对象作为this的上下文 ;
    如果该函数没有返回对象,则返回this。

    模拟一个

    function create() {
        // 创建一个空的对象
        let obj = new Object()
        // 将arguments转换成数组,再调用shift方法返回第一个参数,也就是构造函数
        let Con = [].shift.call(arguments)
        // 链接到原型
        obj.__proto__ = Con.prototype
        // 绑定this,执行构造函数(因为apply会自动执行函数,注意现在的argument里面只有传递进来的属性值)
        let result = Con.apply(obj, arguments)
        console.log('obj--->', typeof obj, obj)
        console.log('result--->', typeof result, result)
        // 这里进行判断,如果构造函数最后有return操作,那就返回构造函数里面那个对象,没有则返回obj
        // 其实就是对应我们上面所说的那个隐形返回
        return typeof result === 'object' ? result : obj
    }
    

    关于最后return模拟返回值, 来举例子打印一下一下明白了

    function Person (name, age) {
        this.name = name
        this.age = age
        this.say=function(){
          console.log('hello')
        }
        return this
    }
    let a = create(Person, '嘟嘟', 18) // {name = '嘟嘟', age = 18}

    返回this

    不返回this

    function Person (name, age) {
        this.name = name
        this.age = age
        this.say=function(){
          console.log('hello')
        }
       // return this
    }
    let a = create(Person, '嘟嘟', 18) // {name = '嘟嘟', age = 18}

    3.2 、第二种实现方式

    function newOperator(ctor, ...args) {
      if (typeof ctor !== 'function') {
        throw new TypeError('Type Error');
      }
      const obj = Object.create(ctor.prototype);
      const res = ctor.apply(obj, args);
    
      const isObject = typeof res === 'object' && res !== null;
      const isFunction = typeof res === 'function';
      return isObject || isFunction ? res : obj;
    }

    4、模拟一个instanceof

    instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

    使用场景:

    function Car(make, model, year) {
      this.make = make;
      this.model = model;
      this.year = year;
    }
    const auto = new Car('Honda', 'Accord', 1998);
    
    console.log(auto instanceof Car);
    // expected output: true
    
    console.log(auto instanceof Object);
    // expected output: true

    模拟一个

    const myInstanceof = (left, right) => {
      // 基本数据类型都返回false
      if (typeof left !== 'object' || left === null) return false;
      let proto = Object.getPrototypeOf(left);
      while (true) {
        if (proto === null) return false;
        if (proto === right.prototype) return true;
        proto = Object.getPrototypeOf(proto);
      }
    }


    5、如何实现Promise.allSettled()方法

    const promise1 = Promise.resolve(3);
    const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
    const promises = [ promise1, promise2];
      如何实现Promise.allSettled()方法

    输入:
    Promise.allSettledDemo(promises).then((results) => results.forEach((result) => console.log(result)));
    输出结果:
    {status:"fulfilled",value:3}
    {status:"rejected",err: "foo"}

    打印window看下

    注意点
    
    1、Promise.allSettled()本来就有,一开始我方法写错了,运行结果是对的,其实调用的并不是我的方法为了区别名字,改个区别一下
     2、Promise本来就是一个构造函数,如果需要用到里面的方法 需要new 一个也就是实例化一个对象。
    3、也不要挂载prototype上否则会报错not function

    模拟代码

    Promise.allSettledDemo= function(promises){
      return new Promise((resolve, reject)=>{
        let arr=[]
        let fulfilledCount = 0
        const itemNum = promises.length
        for(let i=0; i< promises.length; i++){
          promises[i].then((res)=>{
            fulfilledCount++;
            arr.push({status: "fulfilled", value: res})
            if (fulfilledCount === itemNum) {
                resolve(arr);
            }
          }).catch((error)=>{
            fulfilledCount++;
            arr.push({status: "rejected", err: error})
            if (fulfilledCount === itemNum) {
                resolve(arr);
            }
           })
        }
       })
    }

    输入:

    Promise.allSettledDemo(promises).
      then((results) => results.forEach((result) => console.log('test---', result)));

     

    6、如何实现Promise.all() 方法

    Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

    Promise.myAll = function (promiseArr) {
      return new Promise((resolve, reject) => {
        const ans = [];
        let index = 0;
        for (let i = 0; i < promiseArr.length; i++) {
          promiseArr[i].then(res => {
            ans[i] = res;
            index++;
            if (index === promiseArr.length) {
              resolve(ans);
            }
          })
          .catch(err => reject(err));
        }
      })
    }

    打印结果:

    const p1 = new Promise((resolve, reject) => {
      setTimeout(() => resolve('p1'), 1000)
    })
    
    const p2 = new Promise((resolve, reject) => {
      setTimeout(() => resolve('p2'), 5000)
    })
    
    Promise.myAll([p1, p2]).then(rets => {
       console.log('myAll---->', rets) // ['p1','p2']
    })

    7、如何实现Promise.race() 方法

    Promise.race = function(promiseArr) {
      return new Promise((resolve, reject) => {
        promiseArr.forEach(p => {
          // 如果不是Promise实例需要转化为Promise实例
          Promise.resolve(p).then(
            val => resolve(val),
            err => reject(err),
          )
        })
      })
    }

    -------陆续更新中-------

  • 相关阅读:
    QQ邮箱自动删除邮件脚本
    5ppm高精度自动同步标准化考场时钟系统
    GPS时钟之户外防水防雷细节
    C/C++ Compile Run插件,使用某些头文件出现重定义的错误,解决方法为修改MinGW的路径
    7zip 通过指令压缩 仅存储压缩 分压缩卷 / 对文件夹里的文件进行解压,解压到对应文件名所在的文件夹上
    循环队列FIFO
    cglib和jdk代理的字节码生成配置
    SpringXML的beans标签后的一串网址相关的属性有什么用
    service和server这两个单词的区别
    没有代码提示的地方,前后引用记得用复制不要手打
  • 原文地址:https://www.cnblogs.com/pikachuworld/p/15159243.html
Copyright © 2020-2023  润新知