用闭包实现面向对象系统

2017-03-20  本文已影响0人  yongningfu

闭包实现面向对象设计

闭包的思想是: 一个函数想用一个引用一个外部变量,但是有不想让这个变量暴露在全局环境中,那么就使用闭包。闭包一般有两种使用形式,一个是立即执行的闭包,一种是用时执行的闭包。两种有和区别呢?
立即执行的闭包,用于全局创建一个闭包对象
用时执行的闭包,可用于全局创建多个闭包对象

//立即执行的模式
var matchEmail = (function() {
  var regx = /^\w+(\.\w+)*@\w+\.\w{2,3}(\.\w{2,3})?$/;
  return function(email) {
      return regx.test(email);
  }
})();

console.log(matchEmail('535.fu@qq.com'));

//用时执行的模式

var matchEmail2 = function() {
  var regx = /^\w+(\.\w+)*@\w+\.\w{2,3}(\.\w{2,3})?$/;
  return function(email) {
      return regx.test(email);
  }
}

var matchEmail2 = matchEmail2();
console.log(matchEmail('535.fu@qq.com'));

两者有啥区别呢?容易看出,用时执行模式,每次在创建一个新的matchEmail2时候,都会新建一个闭包,和创建一个新的 regx
立即执行啥时候用呢? 一般是在封装的遍历在函数引用中都是有同一个时,如果不同情况需要使用多个,那么使用 用时执行
很显然,我们如果想要创建一个对象系统的话,需要用用时执行模式

var Events = function() {
  var handlers = {};
  var subscribe = function(type, handler) {
    if (!handlers[type]) {
      handlers[type] = [];
    }
    handlers[type].push(handler);

    //存储当前这个handler是否被订阅
    var isSubscribed = true;
    //每次执行一个订阅函数,返回一个取消订阅回调,只要使用这个函数,那么就取消
    return function unsubscribe() {
      if (!isSubscribed) return; //防止多次执行
      isSubscribed = false;
      const index = handlers[type].indexOf(handler);
      handlers[type].splice(index, 1);
    }
  }

  function dispatch(type) {
    if (handlers[type]) {
      for (let i = 0; i < handlers[type].length; i++) {
        handlers[type][i]();
      }
    }
  }


  //闭包对象系统,返回一个对象
  return {
    subscribe,
    dispatch
  }
}

//创建一个event对象
var event = Events();
//创建另外一个event对象
var event1 = Events();

var unSubscribe = event.subscribe('click', function() {console.log('event click')});
event1.subscribe('click', function() {console.log('event1 click')});


event.dispatch('click');
event1.dispatch('click');
unSubscribe();
event.dispatch('click');

上面创建的两个对象 event event1 互不干扰
利用闭包创建对象系统的话,利用闭包封装想用的局部变量,然后返回一个对象,对象里面是向外提供的接口

tips:上面的订阅一个函数,然后返回一个取消点阅函数,也是一种非常不错的发布 取消点阅模式中的编程思想哦,利用闭包,在订阅的时候就封闭了订阅时的函数,那么取消点阅的时候,就一定能访问到这个函数

上一篇 下一篇

猜你喜欢

热点阅读