介绍防抖节流原理、区别以及应用,并用Javascript进行实现

  1. 防抖

    • 原理:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
    • 使用场景:

          * 提交按钮场景: 防止多次提交按钮,只执行最后提交的一次
          * 搜索框联想场景:防止联想发送请求,只发送最后一次输入
    • 简易版本实现

      function debounce(fn, delay) {
            let timer = null
            return (...args) => {
              clearTimeout(timer)
              timer = setTimeout(() => {
                fn.apply(this, args)
              })
            }
      }
    • 立即执行版

          * 立即执行函数,然后等到停止触发n秒后,才可以重新触发执行。
      function debounce(fn, delay, immediate) {
            let timer;
            return (...args) => {
              if (timer) clearTimeout(timer)
              if (immediate) {
                const callNow = !timer
                timer = setTimeout(() => {    
                  timer = null
                }, delay)
                if (callNow) fn.apply(this, args)
              } else {
                timer = setTimeout(() => {
                  fn.apply(this, args)
                }, delay)
              }
            }
      }
  2. 节流

    • 原理:规定一个单位时间内,只能触发一次函数。如果这个单位时间内多次触发函数,只有一次生效。
    • 使用场景

            * 拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动
            * 缩放场景:监控浏览器resize
    • 使用定时器实现

      function throttle(fn, delay) {
            let timer
            return (...args) => {
              if (!timer) {
                timer = setTimeout(() => {
                  timer = null
                  fn.apply(this, args)
                }, delay)
              }
            }
      }

    闭包

    1. 什么是必闭包

         可在内部函数访问外部函数的作用域。在javascript中,每当创建一个函数,闭包就会在函数创建的同时创建出来。
    2. 优点

      * 可从内部函数访问外部函数作用域中的变量,且访问到的变量长期驻扎在内存中,可供之后使用
      * 避免变量污染全局
      * 把变量存到独立作用域,作为私有成员存在
    3. 缺点

      * 对内存消耗有负面影响。因内存函数保存对外层函数引用,导致无法垃圾回收,增大内存使用量
    4. 应用场景

      • 循环中创建闭包,防止取到意外值

        for(var i = 0; i < 3; i ++) {
              document.getElementById('id'+i).onfocus = function() {
                alert(i)
              }
        }
        //使用闭包解决
        function makeCallBack(num) {
              return function() {
                alert(num)
              }
        }
        for(var i = 0; i < 3; i ++) {
            document.getElementById('id'+i).onfocus = makeCallBack(i)
        }
      • 模块封装

        var A = (function(){
            var foo = 0; //声明为模块私有变量,外界无法访问
            function A() {}
            A.prototype.bar = function B() {
              return foo
            }
            return A
        }())

      事件循环机制(node、浏览器)

      为什么会有Event Loop

      Javascript任务分两种`同步`和`异步`,`同步任务`是直接放在主线程上排队一次执行,`异步任务`会放在任务队列中,若有多个异步任务,则需要在任务队列中排队等待,任务队列类似缓冲区,任务下一步会被移动到`调用栈`然后主线程执行调用栈 Javascript是`单线程`的

      Promise的特性、优缺点,内部是如何实现的,动手实现Promise

      1. promise基本特性

        • 三种状态: pendingfulfilledrejected
        • 接受一个回调函数作为参数,该回调函数接受两个参数,分别为resolvereject;另外resolve的值除了正常值以外,还可能是一个Promise对象的实例;reject通常是error对象实例
        • then方法返回一个新的Promise实例,并接收两个参数onResolved(fufilled状态回调);onRejected(reject状态回调,改参数可选)
        • catch方法返回一个新的Promise实例
        • finally方法不管Promise状态如何都会执行,该方法回调函数不需要接受任何参数
      2. 简单版本

        class Promise {
          constrcutor (executor) {
              ths.state = 'pending'
              this.value = undefined
              this.reason = undefined
              let resolve = value => {
                  if (this.state === 'pending') {
                      this.state = 'fulfilled'
                      this.value = value
                  }
              };
              let reject = value => {
                  if (this.state === 'pending') {
                      this.state = 'rejected'
                      this.reason = reason
                  }
              };
              try {
                  executor(resolve, reject)
              } catch (err) {
                  reject(err)
              }
          }
          then (onFulfilled, onRejected) {
              if (this.state == 'fulfilled') {
                  let x = onFulfilled(this.value)
              }
              if (this.state === 'rejected') {
                  let x = onRejected(this.reason)
              }
          }
        }
      3. 面试够用版

        function myPromise(constructor) {
        let self = this;
        self.state = 'pending'; //定义状态改变前初始状态
        self.value = unbdefined; //定义状态为resolved的时候的状态
        self.reason = undefined; //定义状态为rejected的时候的状态
        function resovle (value) {
            //两个==='pending' 保证了状态的改变是不可逆转的
            if (self.state === 'pending') {
                self.value = value
                self.status = 'resolved'
            }
        }
        function reject(reason) {
            if (self.state === 'pending') {
                self.reason = reason;
                self.status = 'rejected'
            }
        }
        
        // 捕获构造函数异常
        try {
            constructor(resolve, reject)
        } catch (err) {
            reject(err)
        }
        }
        myPromise.prototype.then = function(onFulfilled, onRejected) {
        let self = this;
        switch (self.status) {
            case 'resolved': onFulFilled(self.value); break;
            case 'rejected': onRejected(self.reason); break;
            default:
        }
        }

//测试
var p = new myPromise((resolve, reject) => {resolve(1)})
p.then((x) => {console.log(x)})  //输出
```
  1. typeof返回一个表示类型的字符串
    typeof的结果列表
类型结果
Undefined"undefined"
Null"object"
Boolean"boolean"
Number"number"
String"string"
Symbol"symbol"
Function"function"
Object"object"

wudaxue
0 声望0 粉丝