闭包 构建函数 简单工厂模式

Posted t_evening

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了闭包 构建函数 简单工厂模式相关的知识,希望对你有一定的参考价值。

首先说说闭包,闭包在我们实际开发中处处被用到,那个它到底是个什么东西呢?

var user=(function(){
    var USER={
      name:"mapleTao",
      password:"123456"
    }
    return {
      getName:function(){
        return USER.name;
      },
      getPassword:function(){
        return USER.password;
      }
    }
  })();
  console.log(user.getName())
  console.log(user.getPassword())
  console.log(USER)

  

上面就是一个简单的闭包,输出结果为mapleTao,123456,error;让我们先来解析下这个例子干了什么,我们先声明了一个叫user的变量,后面是一个闭包,闭包分成两部分,一部分是前面的匿名函数,后面是该函数的调用,简单点说就是立即执行了这个函数并返回一个对象。对象中包括了两个获取值的方法。在js中是没又常量这也说法的,但是呢,因为js是一门比较灵活的语言,所以呢我们通过闭包就创建了一个这样的“常量”,上面的例子只提供给你获取值的方法,但是呢,你并不能修改USER的内容,这个像不像java中的常量呢?

变量又两种,一种是全局变量,一种是局部变量,我们都知道全局变量是在所有的地方都能访问到,这是比较危险的,因为所有人都能修改它,它的作用域太大了。还有一种是局部变量,顾名思义,局部变量就是一个小区域的变量,我们能在函数内部找到它,但是在外面你是找不到它的。闭包就可以做到让我们在函数外部访问到函数内部的变量。

闭包的好处:

1:不会污染全局变量。上面这个例子中是无法直接访问到user的

2:让一个变量永久保存到内存中,不会被回收系统回收掉。我们能通过它提供的方法访问到它,说明它是保存到内存中的而且也没有被清掉

3:创建立即执行。

4:形成一个独立的作用域。上面这个例子中,匿名函数内部就是一个独立的作用域,这个作用域里面的变量外部无法直接获取。

缺点

1:占内存。因为它不会被gc回收,所以会占内存空间,严重可能会导致内存泄漏。

2:外部可以改变内部函数的值。

闭包: 函数外可以访问到函数内部的变量。

通过他的解释就知道闭包的使用了,就是你需要使用到的变量,但是这个变量不能被直接访问,就比如比较函数:

// @pramater name string
function
compare(name){ return function (n,m) { if (name) { n = n.name m = m.name } if (n>m) { return 1 }else if (n == m) { return 0 }else if (n < m) { return -1 } } }

上述比较函数提供一个name值来,可以根据对象的属性或者对象本身进行排序。

接下来聊聊构造函数,js中虽没有类的说法,但是呢我们可以通过不同的方法来让它实现这个效果。不多说上代码。

 function Book(name,type,author){
    if(this instanceof Book){
      this.name=name;
      this.type=type;
      this.author=author;
    }else{
      return new Book(name,type,author);
    }
  };
  Book.prototype={
    introduce:function(){
      console.log(this.name+"--"+this.type+"--"+this.author);
    }
  };

  var html=new Book("h5开发","Book","maple");
  var js=Book("设计模式","Book","tao");
 
  HTML.introduce();
  js.introduce();

上面这段代码就是一个简单的构造函数,通过构造函数,生成相似的对象。简单来说构造模式就是用来创建相似对象的函数,也就是对一些相同代码的封装,简单点来说就是优化,将一些重复使用的代码抽象出来。这个可以减少代码量,增加代码的复用性。

上面这个构造函数也用到了原型模式,原型模式在我看来也是一种优化,因为对象的原型是一个引用类型,引用类型比较特殊,它是指向堆的,所以不会重复分配内存,可以减少内存的占用率,而且prototype是一个函数自带的属性,写在里面可读性更强。

  //报纸
  function Newspaper(name,type,author){
    if(this instanceof Newspaper){
      this.name=name;
      this.type=type;
      this.author=author;
    }else{
      return new Newspaper(name,type,author);
    }
  };
  Newspaper.prototype={
    introduce:function(){
      console.log(this.name+"--"+this.type+"--"+this.author);
    }
  };
  //杂志 
  function Magazine(name,type,author){
    if(this instanceof Magazine){
      this.name=name;
      this.type=type;
      this.author=author;
    }else{
      return new Magazine(name,type,author);
    }
  };
  Magazine.prototype={
    introduce:function(){
      console.log(this.name+"--"+this.type+"--"+this.author);
    }
  };

上面我们又创建了两个构造函数,一个是报纸构造函数,一个是杂志构造函数,但是如果你交给别人用的话,不可能给对方三个函数,而且在用法方面可能会有点问题,所以这个时候我们的封装一下。提供一个接口。

我们用简单工厂模式封装下以上代码。

var createFactory=function(name,type,author){
    var obj;
    switch(type){
      case "Book":
        obj=new Book(name,type,author);
        break;
      case "Newspaper":
        obj=new Newspaper(name,type,author);
        break;
      case "Magazine":
        obj=new Magazine(name,type,author);
        break;
    }
    return obj;
  };
  var mag=createFactory("剎漫画","Magazine","漫画");
  var news=createFactory("新闻","Newspaper","新闻");
  var bk=createFactory("一本书","Book","书");
  console.log("-------------");
  mag.introduce();
  news.introduce();
  bk.introduce();
  console.log("-------------");

上面就是一个简单的工厂模式,createFactory就是一个书店,但我们去买书的时候,就知道告诉它我们买一本杂志或者报纸啊,后面的就交给书店老板解决了。

上面三个函数有很多共同点,这个时候我们可以进一步的优化代码,我们可以把相同的抽象出来来,不同的再判断,如下。

var createBook=function(name,type,author){
    var o={};
    o.name=name;
    o.type=type;
    o.author=author;
    o.introduce=function(){
      console.log(this.name+"--"+this.type+"--"+this.author+"--"+this.status);
    }
    if(type==="Book"){
      o.status=0;
    }
    if(type==="Magazine"){
      o.status=1;
    }
    if(type ==="Newspaper"){
      o.status=2;
    }  
    return o;
  }
  var mag1=createBook("剎漫画","Magazine","漫画");
  var news1=createBook("新闻","Newspaper","新闻");
  var bk1=createBook("一本书","Book","书");
  mag1.introduce();
  news1.introduce();
  bk1.introduce();

但是,从上面这段代码来看,但对象很多时会特别复杂,很难维护,而且introuce每次都会去实例一次,所以还可以想办法再优化下。

今天就先到这里,咋先去休息下。更多精彩请听下回分解。

以上是关于闭包 构建函数 简单工厂模式的主要内容,如果未能解决你的问题,请参考以下文章

闭包函数与装饰器

Spark闭包与序列化

常用的设计模式

关于js的设计模式(简单工厂模式,构造函数模式,原型模式,混合模式,动态模式)

少女学习日记——函数进阶闭包以及递归

设计模式-简单工厂模式工厂模式抽象工厂模式-(创建型模式)