从JavaScript学习设计模式-01原型模式

原型模式(prototype):是指用原型实例指向建立对象的种类,而且经过拷贝这些原型建立新的对象。javascript

真正的原型继承是做为最新版的ECMAScript5标准提出的,使用Object.create方法来建立这样的对象,该方法建立指定的对象,其对象的prototype有指定的对象(也就是该方法传进的第一个参数对象),也能够包含其余可选的指定属性。例如Object.create(proto, [propertiesObject])java

过程

Prototype => new ProtoExam => clone to new Object;ui

建立一个原型=>new一个原型实例=>拷贝原型实例到新的对象this

// 建立一个原型而且添加一些属性 this.XXX 添加 
  function Person () {
    this.name = 'Uzi'
    this.sex = '21'
    this.age = '男'
    this.getName=function () {
      return `姓名:${this.name}`
    }
  }
  // 经过 .prototype.XXX 方式 添加也可
  Person.prototype.getMsg = function () {
    return `姓名: ${this.name}, 年龄: ${this.age}, 性别:${this.sex}`
  }
  
  // new一个原型实例
  const proto = new Person();  
  // 经过 Object.create 拷贝原型实例 
  const person1 = Object.create(proto);
  const person2 = Object.create(proto);
  person2.name = 'Ming'
  person2.sex = '20'
  person2.age = '男'
  console.log(person1.getName())  // 姓名: Uzi
  console.log(person2.getName())  // 姓名: Ming
  console.log(person1.getMsg())  // 姓名: Uzi, 年龄: 男, 性别:21
  console.log(person2.getMsg())  // 姓名: Ming, 年龄: 男, 性别:20
复制代码

此段代码也证实了:原型挂在实例的原型链上,修改实例不影响原型,即为深拷贝spa

原型模式,通常用于抽象结构复杂,但内容组成差很少,抽象内容可定制,新建立只需在原建立对象上稍微修改便可达到需求的状况。prototype

优势

方法不会从新建立(只要 new 一个原型实例)code

缺点:

  1. 全部的属性和方法都共享
  2. 不能初始化参数

Object.create

定义

建立一个具备指定原型且可选择性地包含指定属性的对象对象

Object.create(proto, [propertiesObject])继承

proto :新建立对象的原型对象ip

propertiesObject :可选。若是没有指定为 undefined,则是要添加到新建立对象的可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)对象的属性描述符以及相应的属性名称。这些属性对应 Object.defineProperties() 的第二个参数。

使用

1.定义原型对象

// 添加属性方法 this.XXX方式
  function Person () {
    this.name = 'Uzi'
    this.sex = '21'
    this.age = '男'
    this.getName=function () {
      return `姓名:${this.name}`
    }
  }
  // 添加属性方法 .prototype.XXX 方式
  Person.prototype.getMsg = function () {
    return `姓名: ${this.name}, 年龄: ${this.age}, 性别:${this.sex}`
  }
复制代码

2.使用 Object.create 拷贝 原型

1.以 Person.prototype 建立对象
const person1 = Object.create(Person.prototype, {
    position:{value: 'ADC', writable: true}
  })
  
  console.log(person1.position)   // ADC
  console.log(person1.getMsg())   // 姓名: undefined, 年龄: undefined, 性别:undefined
  console.log(person1.getName())  // Uncaught TypeError: person1.getName is not a function

复制代码

这说明 person1 就具备 Person 原型方法 getMsg 的方法,可是不具备 Person 下成员属性 name、sex、age、getName

2. 以实例化的 Person 作原型
const proto = new Person();  // 实例化的Person
  const person2 = Object.create(proto, {
    position: { value: 'SUP', writable: true }
  });
  person2.name = 'Ming'
  person2.sex = '20'
  person2.age = '男'
  console.log(person2.position)  // SUP
  console.log(person2.getMsg())  // 姓名: Ming, 年龄: 男, 性别:20
  console.log(person2.getName())  // 姓名: Ming
复制代码

这说明,这样建立的 person2 就具备 Person 的全部的成员属性 name、sex、age、getName以及 getMsg 原型方法; 并添加了一个 position 只读 数据属性;

使用 Object.create 实现子类继承

1.以 Person.prototype 对象,作为 Son 的原型
function Son () {
    Person.call(this);   // 否则没法 Person 成员属性
  }

  Son.prototype = Object.create(Person.prototype, {
    position: { value: '儿子' }
  });

  Son.prototype.sonMethod = function() {
    return this.name || this.position;
  }

  const son1= new Son()
  console.log(son1.position)    // 儿子
  console.log(son1.getMsg())    // 姓名: Uzi, 年龄: 男, 性别:21
  console.log(son1.sonMethod()) // Uzi
  console.log(son1.getName())   // 姓名: Uzi
复制代码
2.以实例化的 Person 对象,作为 Son 的原型
const proto = new Person();

  function Son () {
  }

  Son.prototype = Object.create(proto, {
    position: { value: '儿子' }
  });

  const son1= new Son()
  console.log(son1.position)   // 儿子
  console.log(son1.getMsg())   // 姓名: Uzi, 年龄: 男, 性别:21
  console.log(son1.getName())  // 姓名: Uzi
复制代码

这样 Son 实例化后,就能够获取到 Person 全部的属性及原型方法,以及建立一个只读数据属性 position;

Object.create的实现

Object.prototype.create = function (obj) {
    if (Object.prototype.create) {
      return Object.prototype.create
    } else {
      function F () {
        F.prototype = obj; //以传入参数为原型构造对象
        return new F();
      }
    }
  }
复制代码

由此也能看出返回了一个新对象,深拷贝

Object.create、{}、new Object() 对比

Object.create 指定了拷贝的原型对象,Object.create(null)的时候对象不具有任何原型属性,{}、new Object()、具有对象的原型属性

相关文章
相关标签/搜索