從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()、具有對象的原型屬性

相關文章
相關標籤/搜索