数组的扁平化、单例模式、策略模式

74 阅读3分钟

一、数组的扁平化

数组的扁平化,就是将一个“多维数组”转化成一个“一维数组

    const arr = [1, 2, 3, 4, [5, 6, 7, 8, [9, 10, 11, 12]]]
    console.log(arr);
    console.log([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]);

面试

    function flat(origin) {
      //该函数接收一个参数,也就是你要实现扁平化的一个数组

      // 1.创建一个空数组,用来接收扁平化以后的元素内容
      const newArr = []

      // 2.实现递归函数,实现数组的扁平化
      function fn(fnOrigin) {
        fnOrigin.forEach((item) => {
          if (Object.prototype.toString.call(item) === '[object Array]') {
            // 说明当前item是一个数组,此时需要递归调用 fn 函数
            fn(item)
          } else {
            // 如果当前分支执行,说明 item 一定不是一个数组
            newArr.push(item)
          }
        })
      }
      fn(origin)

      // 3.把处理好的数组(newArr)返回出去
      return newArr
    }
    const flatArr = flat(arr)
    console.log(flatArr)

工作

    console.log(arr);
    console.log(arr.flat(1));
    console.log(arr.flat(2));
    console.log(arr.flat(Infinity));

二、单例模式

设计模式:为了解决某一类问题的一个优化过的代码解决方案

单例模式一个构造函数,一生只能创建一个实例化对象

  • 准备一个变量,默认赋值为 null ,然后再第一次实例化的时候,给这个变量赋值为实例化对象,后续在调用实例化的时候,就不再创建实例化对象了,而是拿到提前准备好的变量
    class Dialog{
      constructor(){
        console.log('在页面中创建了一个弹出层');
      }
    }

    let instance = null
    function newDialog() {
      if(instance === null) {
        instance = new Dialog()
      }
      return instance
    }

    // 第一次调用,创建一个实例化对象然后给到 instance 中,并返回 instance
    let d1 = newDialog()

    // 第二次以及以后所有的调用,都是直接返回 instance
    let d2 = newDialog()
    newDialog()
    newDialog()
    newDialog()
    newDialog()

单例模式升级1

    class Dialog {
      constructor() {
        console.log('在页面中创建了一个弹出层');
      }
    }

    // let instance = null
    // function newDialog() {
    //   if (instance === null) {
    //     instance = new Dialog()
    //   }
    //   return instance
    // }

    // 升级1:原本的 instance 变量为一个全局变量,本次利用自执行函数与闭包将其修改为了局部变量
    const newDialog = (function () {
      // 在自执行函数内创建一个变量(局部变量)
      let instance = null
      return function () {
        if (instance === null) {
          instance = new Dialog()
        }
        return instance
      }
    })()

    const d1 = newDialog()
    const d2 = newDialog()

单例模式升级2

    const Dialog = (function () {
      let instance = null

      class Dialog {
        constructor(title) {
          this.title = ''
          console.log('在页面中创建了一个弹出层')
        }
        setTitle(newTitle) {
          this.title = newTitle
        }
      }
      return function (type) {
        if (instance === null) {
          //当前分支语句的代码,只会在第一次的时候执行
          instance = new Dialog()
        }

        // 此时的位置每一次调用 newDialog 都会执行一次
        instance.setTitle(type)
        return instance
      }
    })()

    const d1 = Dialog('警告')
    console.log(d1);

    // 过了很久之后,第二次调用
    const d2 = Dialog('通用')
    console.log(d2);

三、策略模式

策略模式:为了解决过多的 if...else 的嵌套问题

策略模式的核心(当前案例)

创建一个数据结构,这个结构内存储着各种折扣纪录,对应的值是这个折扣的计算方式

    {
        '8折':商品总价 * 80%
        '7折':商品总价 * 70%
        '5折':商品总价 * 50%
    }

基础版

    // 基础版
    // if ('8折') {
    //   console.log('商品价格的 * 80%');
    // }
    // else if ('85折') {
    //   console.log('商品价格的 * 85%')
    // }
    // else if ('9折') {
    //   console.log('商品价格的 * 90%')
    // }
    // else if ('95折') {
    //   console.log('商品价格的 * 95%')
    // }

策略模式优化

    //策略模式优化
    const calcPrice = (function () {
      /**
       * 当前对象内存储着各种折扣以及对应的打折后的商品总价的计算方式
      */
      const calcList = {
        '80%': (total) => { return (total * 0.8).toFixed(2) },
        '70%': (total) => { return (total * 0.7).toFixed(2) }
      }
      function inner(type, total) {
        /**
         * type:表明当前几折
         * total:打折前的商品总价
         * 
         * 调用当前函数是想得到打折后的商品总价,所以我们需要书写一个 return
        */
        return calcList[type](total)
      }
      return inner
    })()


    console.log(calcPrice('80%', 500));
    console.log(calcPrice('80%', 1000));
    console.log(calcPrice('80%', 876.3));

策略模式2

    const calcPrice = (function () {
      const calcList = {
        '80%': total => (total * 0.8).toFixed(2),
        '70%': total => (total * 0.7).toFixed(2),
        '60%': total => (total * 0.6).toFixed(2)
      }

      /**
       * !在 JS 中,所有的引用数据类型都可以当成一个对象来使用
      */
      function inner(type, total) {
        return calcList[type](total)
      }

      inner.add = function (type, fn) {
        calcList[type] = fn
      }

      inner.sub = function (type) {
        delete calcList[type]
      }

      inner.getList = function () {
        return calcList
      }

      return inner
    })()


    // console.log(calcPrice('80%', 500));
    // console.log(calcPrice('80%', 1000));
    // console.log(calcPrice('80%', 876.3));

    // calcPrice.add('50%', total => (total * 0.5).toFixed(2))
    // calcPrice.add('88%', total => (total * 0.88).toFixed(2))

    // calcPrice.sub('60%')
    console.log(calcPrice.getList());