js闭包和设计模式

闭包生成的三个必要条件:
(1)在函数a内部直接或间接返回一个函数b。
(2)a函数内部使用着b函数的私有变量。
(3)a函数外部有一个变量接收着函数b。
这个不会销毁的a函数的执行空间叫做闭包空间。
把函数a里面返回的函数b叫做函数A的闭包函数。

function a() {
      // 这个 num 变量就是函数 a 的私有变量
      // var num = 100
      return function b() {
        console.log(num+1)
      }
    }

闭包的特点:
(1)延长了变量的生命周期。
(2)利用闭包函数可以访问函数内部的私有变量。
(3)保护私有变量不被外界访问。

闭包的缺点:
当一段内存空间中有一个不会被销毁的东西一直存在,会出现内存占用,如果过多会导致内存溢出。
闭包的作用:
(1)当需要延长变量的声明周期的时候用闭包函数来解决。
(2)需要访问某一个函数内部的私有数据的时候用闭包函数解决。

二、js设计模式
设计模式是针对特定问题给出的简洁而优化的处理方案
常用的设计模式如下:
(1)单例模式
让一个构造函数一辈子只有一个实例对象。
单例模式的核心代码如下:

function Person() {
    this.name = 'Jack'
 }
 var instance = null
 function singleton() {
    if (instance === null) {
      instance = new Person()
    }
      return instance
 }
var p1 = singleton()

(2)组合模式
把若干个启动方式一样的构造函数放在一起,通过总开关启动,这些构造函数都启动。
实现组合模式的三个条件:
需要一个承载所有构造函数实例的数组;
需要一个方法,向数组里面添加内容;
需要一个方法,能把数组里面的所有内容启动了。
应用如下:

// 一个构造函数的启动方式
    class Play {
      constructor () {}
      // 这个构造函数的启动方法
      init () {
        console.log('开始玩游戏')
      }
    }
    class Eat {
      constructor () {}
      init () {
        console.log('去吃饭')
      }
    }
    class Sleep {
      constructor () {}
      init () {
        console.log('去睡觉')
      }
    }
    // 组合模式的代码
    class Compose {
      constructor () {
       // 用来承载每一个实例的数组
        this.composeArr = []
      }
      	// 向数组里面添加内容
      add (instance) {
        this.composeArr.push(instance)
      }
      // 把数组里面的每一个内容调用了
      init () {
        console.log('总开关启动了')
        this.composeArr.forEach(item => item.init())
      }
    }

    // c 就是一个总开关
    var c = new Compose()
    // 每一次执行 add 方法就是向总开关上添加内容
    c.add(new Play())
    c.add(new Eat())
    c.add(new Sleep())

    // 只要我的总开关一启动
    // 里面的每一个构造函数就同时都启动了
    c.init()
    console.log(c)

(3)观察者模式
又称发布/订阅模式
让观察者看着被观察者,只要数据改变了,就让观察者做些事情。
从观察者角度:

 1. 被观察者
    class Student {
      constructor () {
        // 一个学生本身的状态, 就应该是好好学习
        this.state = '好好学习'
        // 准备一个数组,观察者放数组里
        this.observers = []
      }
      // 可以改变状态的方法
      setState (value) {
        this.state = value
        // 状态一旦改变, 就要通知观察者        this.notify()
      }
      // 获取自己的状态
      getState () {
        return this.state
      }
      // 添加观察者
      attach (observer) {
        this.observers.push(observer)
      }
      // 通知 this.observers 数组里面的每一个人, 状态改变了
      notify () {
        this.observers.forEach(item => item.qingjiazhang( this.state ))
      }

    }
    // 2. 观察着
    class Observer {
      // constructor 就相当于 es5 的构造函数体 => 构造器
      constructor (name) {
        // 用它来标明一下我是班主任还是年级主任还是教务主任
        this.name = name
      }
      // 方法, 就是观察者能触发的技能
      qingjiazhang (state) {
        console.log(`我是 ${ this.name }, 因为你 ${ state }, 我要请你家长来!`)
      }
    }

    var xiaoming = new Student() // 被观察者
    var banzhuren = new Observer('班主任') // 观察者
    var jiaowuzhuren = new Observer('教务主任') // 观察者
    // 让班主任看着小明
    xiaoming.attach(banzhuren)
    // 让教务主任看着小明
    xiaoming.attach(jiaowuzhuren)
    // 当小明状态改变的时候, xiaoming.observers 这个数里里面的每一个对象的调用技能
    xiaoming.setState('玩手机')

从发布/订阅角度:

 class Observer {
      constructor () {
        // 准备的消息盒子
        this.message = {}
      }
        // 订阅的方法
// type 事件类型, 你要订阅的类型
        // fn 事件处理函数, 你要给这个类型订阅一个什么行为
      on (type, fn) {
        // 向消息盒子里面添加成员
        // 判断消息盒子里面有没有成员        
if (!this.message[type]) {
          // 表示 this.message 里面没有这个成员
          this.message[type] = []
        }
//没有成员直接把成员push进去
        this.message[type].push(fn)
      }
      // 取消订阅的方法
      off (type, fn) {
        // 删除消息盒子里面的某一个成员
        // 先看看有没有这个事件类型, 如果没有, 不需要取消
        // 如果由才需要取消
        if (!this.message[type]) return
        // 取消这个数组里面和 fn 一样的那个事件处理函数
        //   使用一个 filter 方法
        this.message[type] = this.message[type].filter(item => item !== fn)
      }

      // 发布的方法
      emit (type) {
        // 执行消息盒子里面的某一个对应的处理函数
        // 判断你有没有订阅过, 如果没有订阅过, 直接return
        if (!this.message[type]) return
        // 如果你订阅过, 那么就执行一下
        this.message[type].forEach(item => item())
      }
    }

    // 将来使用的时候
    var o = new Observer()

    // 订阅事件
    o.on('click', handlerA)
    o.on('click', handlerB)

    // 取消订阅事件
    // o.off('click', handlerA)

    // 发布事件
    // 把你订阅好的事件处理函数都给你触发了
    console.log(o)

    // 准备事件处理函数
    function handlerA() { console.log('我是事件处理函数 handlerA') }
    function handlerB() { console.log('我是事件处理函数 handlerB') }

“家中逆战,无畏疫情!”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值