最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 工厂模式,构造器模式和原型模式

    正文概述 掘金(面屏思过)   2021-05-03   413

    一、工厂模式

    工厂模式属于创建型模式,它提供了一种创建对象的最佳方式。我们在函数内部创建一个对象,赋予对象属性和方法,并通过return返回这个对象

    function createPerson(name, age, job) {
        var o = new Object()
        o.name = name
        o.age = age
        o.job = job
        o.sayName = function() {
          console.log(this.name)
        }
        return o
      }
      var person1 = createPerson('caoyuan', 25, 'Software engineer')
      var person2 = createPerson('neil', 23, 'Software engineer')
      console.log(person1) // {name: "caoyuan", age: 25, job: "Software engineer", sayName: ƒ}
      console.log(person2) // {name: "neil", age: 23, job: "Software engineer", sayName: ƒ}
    

    二、构造函数模式

    构造模式和工厂模式创建对象的不同点在于;

    1. 没有显式的创建对象
    2. 直接将属性和方法赋值给了this对象
    3. 没有return对象
    function Person(name, age, job) {
        this.name = name
        this.age = age
        this.job = job
        this.sayName = function() {
          console.log(this.name)
        }
      }
      let person1 = new Person('caoyuan', 25, 'Software Engineer')
      let person2 = new Person('neil', 23, 'Software engineer')
      person1.sayName()
      person2.sayName()
    

    以这种方式调用构造函数实际会经历一下四个步骤

    1. 创建一个对象
    2. 将构造函数的作用域赋给新对象(因此this就指向这个对象)
    3. 执行构造函数种的代码(为这个新对象添加属性)
    4. 返回对象

    寄生构造函模式

    这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装对象的代码,然后再返回新创建的对象。

    function Person(name, age, job) {
        var o = new Object()
        o.name = name
        o.age = age
        o.job = job
        o.sayName = function() {
          console.log(this.name)
        }
        return o
      }
      let friend = new Person('neil', 25, 'software Engineer')
      friend.sayName() // neil
    

    以上就是例子,把new操作符抛去,这个模式和工厂模式一模一样。构造函数在不返回值的情况下,默认会返回新对象实例,而通过构造函数的末尾添加一个return语句,可以重写调用给构造函数时返回的值。 如下例子

    function SpecialArray () {
        // 创建数组
        var values = new Array()
        // 添加值
        values.push.apply(values, arguments)
        // 添加方法
        values.toPipedString = function() {
          return this.join('|')
        }
    
        // 返回数组
        return values
    
      }
      var color = new SpecialArray('1','2','3')
      console.log(color.toPipedString()) // 1|2|3
    

    稳妥构造函数模式 稳妥对象是指没有公共属性, 方法也不引用this的对象。适合在安全的环境中,或者防止数据被其他应该改动时使用

    稳妥模式遵循与寄生构造函数类似的模式,但 有两点不同;

    1. 创建新对象的实例不引用this;
    2. 不使用new操作符调用构造函数
    function Person(name, age, job) {
        var o = new Object()
        o.sayName = function() {
          console.log(name)
        }
        return o
      }
    
      let person = Person('neil', 25, 'software Engineer')
      person.sayName() // neil
    

    作用域安全的构造函数

    通过代码介绍下作用域安全的构造函数
    function Person(name, age, job) {
        this.name = name
        this.age = age
        this.job = job
      }
     var person = Person('neil', 25, 'Softwate Engineer')
     console.log(window.age) // 25
    
    

    假设用上述这种方式调用,this指向window,那么值也就在window上了,那么怎么才能解决这种问题呢, 修改代码如下

    function Person(name, age, job) {
        if (this instanceof Person) {
          this.name = name
          this.age = age
          this.job = job
        } else {
          return new Person(name, age, job)
        }
      }
      var person = Person('neil', 25, 'software Engineer')
      console.log(window.age) // undefined
      console.log(person.age) // 25
    

    通过instanceof来判断当前this是否是person实例上的,现在看上去好像没有什么问题了,那么假设用了构造函数窃取模式的继承且不使用原型链,这个继承可能就被破坏了

    function Polygon(sides) {
        if (this instanceof Polygon) {
          this.sides = sides
          this.getArea = function() {
            return 0
          }
        } else {
          return new Polygon(sides)
        }
      }
    
      function Rectangle(width, heigth) {
        Polygon.call(this, 2) 
        this.width = width
        this.heigth = heigth
        this.getArea = function () {
          return this.width * this.heigth
        }
      }
      let rect = new Rectangle(5, 10)
      console.log(rect.sides) // undefined
    
    

    你会发现,rect.sides为undefined,为啥呢,Polygon这个实例是安全的,但是,Rectangle中是通过call来继承Polygon的sides属性,这是因为this对象不是Polygon的实例,所以创建了一个新的Polygon对象,Rectangle中并没有sides属性。如果构造函数窃取结合使用原型链和寄生模式就可以解决这个问题了,代码如下

    function Polygon(sides) {
        if (this instanceof Polygon) {
          this.sides = sides
          this.getArea = function() {
            return 0
          }
        } else {
          return new Polygon(sides)
        }
      }
    
      function Rectangle(width, heigth) {
        Polygon.call(this, 2) 
        this.width = width
        this.heigth = heigth
        this.getArea = function () {
          return this.width * this.heigth
        }
      }
      Rectangle.prototype = new Polygon()
      let rect = new Rectangle(5, 10)
      console.log(rect.sides) // 2
    

    三、原型模式

    我们创建的每个函数都有prototype属性,这个属性是一个指针,指向对象,而这个对象包含可以由特定类型的所有实列共享的属性和方法。prototype就是通过调用构造函数而创建的那个实例对象的原型对象。

      function Person() {
      }
      Person.prototype.name = 'caoyuan'
      Person.prototype.age = '25'
      Person.prototype.sayName = function() {
        console.log(this.name)
      }
      let person1 = new Person()
      let person2 = new Person()
      person2.sayName()
      person1.sayName()
      console.log(person1.sayName == person2.sayName)
    
    

    动态原型模式

    它把所有信息都封装在了构造函数中,而通过在构造函数中初始化原型,也保持了同时使用构造函数和原型的优点

    function Person(name, age, job) {
        this.name = name
        this.age = age
        this.job = job
        // 方法
        if (typeof this.sayName != 'function') {
          Person.prototype.sayName = function() {
            console.log(this.name)
          }
        }
      }
      let person = new Person('neil', 25, 'Software Engineer')
      person.sayName()
    
    

    四、组合使用构造函数模式和原型模式

    创建自定义对象最常见的方式,就是组合使用构造函数模式和原型模式。

    1. 构造函数模式定义实例的属性
    2. 原型模式用于定义方法和共享的属性
    function Person(name, age, job) {
      this.name = name
      this.age = age
      this.children = ['1', '2']
    }
    Person.prototype.sayName = function() {
      console.log(this.name)
    }
    
    let person1 = new Person('caoyuan', 25, 'Software Engineer')
    let person2 = new Person('neil', 23, 'Software Engineer')
    
    person1.children.push('3')
    console.log(person1.children) // Array [1,2,3]
    console.log(person2.children) // Array [1,2]
    console.log(person1.children === person2.children) // false
    console.log(person1.sayName === person2.sayName) // true
    

    起源地下载网 » 工厂模式,构造器模式和原型模式

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元