美文网首页
二、创建对象的几个模式

二、创建对象的几个模式

作者: 萘小蒽 | 来源:发表于2019-03-20 15:37 被阅读0次

虽然Object构造函数或对象字面量都可以创建单个对象,但是同时在一个接口创建很多个对象,使用他们会产生大量重复代码。为了解决这个问题,产生了工厂模式构造函数模式

1. 工厂模式

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("YuJia","27","Software Engineer");
var person2 = createPerson("Greg","27","Software Engineer");
  • 优点:可以创建多个相似对象,相对单个去构造对象代码量少。
  • 缺点:不知道创建的对象的类型(下面2会讲到)。

2. 构造函数模式

function Person(name,age,job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName = function(){
         console.log(this.name)    
   };
} 
var person1 = new Person("YuJia","27","Software Engineer");
var person2 = new Person("Greg","27","Software Engineer");
  • 相对于工厂模式,构造函数模式的特点一目了然。
  • 没有显式地创建对象。
  • 直接将属性赋值给了this对象。
  • 没有return语句。
  • 使用new操作符创建对象的新实例。
  • 构造函数模式的过程
  1. 创建一个新的对象。
  2. 将函数的作用域赋给新对象。
  3. 执行构造函数中的代码(为对象赋值新的属性)。
  4. 返回新对象。
  • 深入:对象的constructor(构造函数最初是用来标识对象类型的,但是instanceof操作符要更可靠。
person1.constructor == Person //true
person2.constructor == Person //true
person1 instanceof Person   //true
person2 instanceof Person   //true
person1 instanceof Object   //true
person2 instanceof Object   //true
  • 创建自定义的构造函数意味着将来可以将它的实例标识为一种特殊的类型,这是构造函数模式胜过工厂模式的地方。
  • 上面的person同时是ObjectPerson构造函数的实例,因为所有对象都继承自Object
  • 如果将构造函数直接当函数来运行(不使用new操作符)要考虑作用域,即this的指向.
function Person(name,age,job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName = function(){
         console.log(this.name)    
   };
} ;

// 普通调用,this指向window
Person("YuJia","27","Software Engineer");
window.sayName() // YuJia
//换一个作用域
var o = new Object;
Person.call(o,"Jia","27","Software Engineer")
o.sayName() //Jia
  • 构造函数的缺点

像上面的Person构造函数,在构造多个实例的时候,构造函数内部的方法sayName()都要被重新创建一遍,这就代表指针不一样,导致堆内存占用的代价。与下面的例子在逻辑上是等价的。

function Person(name,age,job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName = new Function("console.log(this.name)");
     //每次创建Person实例,都会重新创建一次sayName
} ;
var person1 = new Person("YuJia","27","Software Engineer");
var person2 = new Person("Greg","27","Software Engineer");
person1.sayName === person2.sayName  ///false
  • 我们可以这样解决构造的多个对象内部方法为同一个指针
function Person(name,age,job){
      this.name = name;
      this.age = age;
      this.job = job;
      this.sayName =  sayName;
} ;
function sayName(){
         console.log(this.name)    
   };
  • 上面的方法可以解决构造Person的多个对象,内部方法都指向外部的sayName(),但是在全局作用域中定义的方法,却只被Person构造方法调用,你让全局作用域情何以堪呢?
  • 更何况如果Person构造函数不只是sayName(),还有多个方法,那我们要在全局作用域下面定义更多的Person私人方法啦?
  • 由此,我们欢迎一下原型模式(👏👏👏👏👏👏)

3. 原型模式

  • 我们创建的每一个函数都有一个prototype(原型)属性,它是一个指针,指向一个对象,这个对象的用途是包含可以有特定类型的所有实例共享的属性和方法。
  • prototype让构造模式上的方法和属性共享(指针都指向同一个地方)
function Person(){
      Person.prototype.name ="小明";
      Person.prototype.age = 27;
      Person.prototype.job = "搬砖";
      Person.prototype.sayName = function(){
         console.log(this.name)    
    };
} ;
var person1 = new Person();
person1.sayName()  // 小明
var person2 = new Person();
person2.sayName()  // 小明
person1.sayName === person2.sayName // true

上面的原型模式下,构造出来的实例person1person2他们共享属性和方法,即他们内部的同名函数指针指向同一个方法。这样不管构造多少实例,内部的方法或者属性,都指占用一个堆。

  • 单用原型模式的缺点
  1. 它省略了为构造函数传递初始化参数环节,导致所有实例在默认情况下都将取得相同的属性值。
  2. 原型的共享本质是最大问题.

4. \color{#c7254e}{构造函数模式}\\color{#c7254e}{原型模式}\组合使用

  • 构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。两种结合使用,每个实例都会有自己的一份实力属性的副本,但同时又共享着对方发的引用,最大限度节省内存,集两种模式的长处。
function Person (name,age,job){
     this.name = name;
     this.age = age;
     this.job = job;
     this.friends = ['Dog','Cat'];
}
Person.prototype = {
    constructor : Person,
    sayName : function(){
       console.log(this.name) ; 
  }
}
var person1= new Person("余嘉",27,"Software Engineer");
var person2= new Person("狗子",2,"看家护院");

上面生成的两个实例,把所有信息属性都封装在了构造函数中,而通过初始化构造函数的原型(重新给原型赋值,断开了与原来默认原型的关系),既保持了自己某些方面的独立性,又公用着同一个方法。

5. 动态原型模式

动态原型模式是基于原型的动态性实现的,即在原型上添加需要的方法和属性(和组合模式相比,不需要给原型重新赋值),来实现实例的共享方法或属性。

function Person(name,age,job){
   //属性
   this.name = name;
   this.age = age;
   this.job = job;
  //方法
  if(type of this.sayName != 'function'){
     Person.prototype.sayName = function(){
     console.log(this.name) ;
     };
   }
}

上面添加方法的时候,在sayName方法不存在的情况下,才会将他添加到原型中,添加方法的过程只会在初次调用时才会执行,此后原型的初始化已经完成了,不需要再修改了。

6. 寄生构造函数模式

这种模式的构造方法有点像工厂模式那样,通过在方法的末尾添加return语句,重新定义通过构造函数模式的new方法默认返回的值。

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
}
var friend = new Person("狗",2,"看家护院");
friend.sayName(); // 狗

这种模式可以在特殊的情况下用来为对象创建构造函数。比如我们想创建一个具有额外方法的特殊数组,我们又不能直接在Array构造函数上直接修改。由此我们可以使用这种模式。

function specialArray(){
   //创建数组
   var values = new Array();
   //添加值
   values.push.apply(values,arguments)
   //添加方法
   values.toPipedstring = function(){
       return this.join("|");
    }
   return values;
 }
var colors = new specialArray("red","blue","green");
console.log(colors.toPipedstring())  //red|blue|green

7. 稳妥构造函数模式(安全执行环境中)

js中有稳妥对象这个概念(管TM谁发明的),稳妥构造函数模式具有以下情况:

  • 没有公共属性
  • 不使用new操作符调用构造函数
  • 创建的实例上的方法不引用this
function Person(name,age,job){
   var o = new Object;
   o.sayName = function(){
   console.log(name) 
   };
  return o
}
var friend = Person("狗",2,"看家护院")

这种模式创建的对象(稳妥对象),除了使用sayName(),没有其他办法访问name的值。即使我们在稳妥对象中添加方法或数据成员,也不可能用其他办法访问到传入构造函数中的原始的数据。

相关文章

  • 二、创建对象的几个模式

    虽然Object构造函数或对象字面量都可以创建单个对象,但是同时在一个接口创建很多个对象,使用他们会产生大量重复代...

  • 2018-03-22

    Boolan C++设计模式二 “对象创建”模式:通过“对象创建”模式绕开new,来避免对象创建(new)过程中所...

  • (GeekBand)C++设计模式 第二周学习笔记

    Factory Method模式 “对象创建”模式 通过“对象创建”模式绕开new,来避免对象创建(new)过程中...

  • javascript面向对象与原型

    昨天我们讲了在面向对象中创建对象的几种方式 工厂模式 构造函数模式 工厂模式创建的对象,像工厂一样来创建对象,创建...

  • 模式设计之 原型模式

    定义 原型模式:原型模式用于创建重复的对象,实现对象的拷贝。这种模式类似于创建型模式,提供了创建对象的最佳模式。 ...

  • JavaScript对象的创建方法

    大纲 前言1、简单方式创建对象的方法2、工厂模式创建对象3、构造函数模式创建对象4、原型模式创建对象5、组合使用构...

  • 设计模式分为三种类型,共23类

    1.创建型模式 创建型模式是处理对象创建的设计模式,试图根据实际情况使用合适的方式创建对象。基本的对象创建方式可能...

  • 设计模式(Design pattern)

    一、分类 1、根据目的分类 创建型模式、结构型模式和行为型模式 创建型模式:“怎样创建对象” -> “对象的创建与...

  • js创建对象及工厂模式

    单体创建对象 工厂模式创建对象

  • 单体创建对象、工厂模式创建对象

    单体创建对象 工厂模式创建对象

网友评论

      本文标题:二、创建对象的几个模式

      本文链接:https://www.haomeiwen.com/subject/hjhzmqtx.html