好程序員分享JavaScript建立對象的方式!

  好程序員分享JavaScript建立對象的方式!JavaScript建立對象的方式有不少,經過Object構造函數或對象字面量的方式也能夠建立單個對象,顯然這兩種方式會產生大量的重複代碼,並不適合量產。接下來介紹七種很是經典的建立對象的方式,他們也各有優缺點。程序員

一、工廠模式

function createPerson(name, job) {  var o = new Object()數組

  o.name = name安全

  o.job = job函數

  o.sayName = function() {    console.log(this.name)this

  }  return ospa

}var person1 = createPerson('Jiang', 'student')var person2 = createPerson('X', 'Doctor')prototype

能夠無數次調用這個工廠函數,每次都會返回一個包含兩個屬性和一個方法的對象對象

工廠模式雖然解決了建立多個類似對象的問題,可是沒有解決對象識別問題,即不能知道一個對象的類型ip

二、構造函數模式

function Person(name, job) {  this.name = name  this.job = job  this.sayName = function() {    console.log(this.name)原型

  }

}var person1 = new Person('Jiang', 'student')var person2 = new Person('X', 'Doctor')

沒有顯示的建立對象,使用new來調用這個構造函數,使用new後會自動執行以下操做

  • 建立一個新對象
  • 這個新對象會被執行[[prototype]]連接
  • 這個新對象會綁定到函數調用的this
  • 返回這個對象

使用這個方式建立對象能夠檢測對象類型

person1 instanceof Object // trueperson1 instanceof Person //true

可是使用構造函數建立對象,每一個方法都要在每一個實例上從新建立一次

三、原型模式

function Person() {

}

Person.prototype.name = 'Jiang'Person.prototype.job = 'student'Person.prototype.sayName = function() {  console.log(this.name)

}var person1 = new Person()

將信息直接添加到原型對象上。使用原型的好處是可讓全部的實例對象共享它所包含的屬性和方法,沒必要在構造函數中定義對象實例信息。

原型是一個很是重要的概念,在一篇文章看懂proto和prototype的關係及區別中講的很是詳細

更簡單的寫法

function Person() {

}

Person.prototype = {

  name: 'jiang',

  job: 'student',

  sayName: function() {    console.log(this.name)

  }

}var person1 = new Person()

將Person.prototype設置爲等於一個以對象字面量形式建立的對象,可是會致使.constructor不在指向Person了。

使用這種方式,徹底重寫了默認的Person.prototype對象,所以 .constructor也不會存在這裏

Person.prototype.constructor === Person  // false

若是須要這個屬性的話,能夠手動添加

function Person() {

}

Person.prototype = {

  constructor:Person

  name: 'jiang',

  job: 'student',

  sayName: function() {

    console.log(this.name)

  }

}

不過這種方式仍是不夠好,應爲constructor屬性默認是不可枚舉的,這樣直接設置,它將是可枚舉的。因此能夠時候,Object.defineProperty方法

Object.defineProperty(Person.prototype, 'constructor', {

  enumerable: false,

  value: Person

})

缺點

使用原型,全部的屬性都將被共享,這是個很大的優勢,一樣會帶來一些缺點

原型中全部屬性實例是被不少實例共享的,這種共享對於函數很是合適。對於那些包含基本值的屬性也勉強能夠,畢竟實例屬性能夠屏蔽原型屬性。可是引用類型值,就會出現問題了

function Person() {

}

Person.prototype = {

  name: 'jiang',

  friends: ['Shelby', 'Court']

}var person1 = new Person()var person2 = new Person()

person1.friends.push('Van')console.log(person1.friends) //["Shelby", "Court", "Van"]console.log(person2.friends) //["Shelby", "Court", "Van"]console.log(person1.friends === person2.friends) // true

friends存在與原型中,實例person1和person2指向同一個原型,person1修改了引用的數組,也會反應到實例person2中

四、組合使用構造函數模式和原型模式

這是使用最爲普遍、認同度最高的一種建立自定義類型的方法。它能夠解決上面那些模式的缺點

使用此模式可讓每一個實例都會有本身的一份實例屬性副本,但同時又共享着對方法的引用

這樣的話,即便實例屬性修改引用類型的值,也不會影響其餘實例的屬性值了

function Person(name) {  this.name = name  this.friends = ['Shelby', 'Court']

}

Person.prototype.sayName = function() {  console.log(this.name)

}var person1 = new Person()var person2 = new Person()

person1.friends.push('Van')console.log(person1.friends)  //["Shelby", "Court", "Van"]console.log(person2.friends) // ["Shelby", "Court"]console.log(person1.friends === person2.friends) //false

五、動態原型模式

動態原型模式將全部信息都封裝在了構造函數中,初始化的時候,經過檢測某個應該存在的方法時候有效,來決定是否須要初始化原型

function Person(name, job) {  // 屬性

  this.name = name  this.job = job  // 方法

  if(typeof this.sayName !== 'function') {

    Person.prototype.sayName = function() {       console.log(this.name)

    }

  }

 

}var person1 = new Person('Jiang', 'Student')

person1.sayName()

只有在sayName方法不存在的時候,纔會將它添加到原型中。這段代碼只會初次調用構造函數的時候纔會執行。

此後原型已經完成初始化,不須要在作什麼修改了

這裏對原型所作的修改,可以當即在全部實例中獲得反映

其次,if語句檢查的能夠是初始化以後應該存在的任何屬性或方法,因此沒必要用一大堆的if語句檢查每個屬性和方法,只要檢查一個就行

六、寄生構造函數模式

這種模式的基本思想就是建立一個函數,該函數的做用僅僅是封裝建立對象的代碼,而後再返回新建的對象

function Person(name, job) {  var o = new Object()

  o.name = name

  o.job = job

  o.sayName = function() {    console.log(this.name)

  }  return o

}var person1 = new Person('Jiang', 'student')

person1.sayName()

這個模式,除了使用new操做符並把使用的包裝函數叫作構造函數以外,和工廠模式幾乎同樣

構造函數若是不返回對象,默認也會返回一個新的對象,經過在構造函數的末尾添加一個return語句,能夠重寫調用構造函數時返回的值

七、穩妥構造函數模式

首先明白穩妥對象指的是沒有公共屬性,並且其方法也不引用this。

穩妥對象最適合在一些安全環境中(這些環境會禁止使用this和new),或防止數據被其餘應用程序改動時使用

穩妥構造函數模式和寄生模式相似,有兩點不一樣:一是建立對象的實例方法不引用this,而是不使用new操做符調用構造函數

function Person(name, job) {  var o = new Object()

  o.name = name

  o.job = job

  o.sayName = function() {    console.log(name)

  }  return o

}var person1 = Person('Jiang', 'student')

person1.sayName()

和寄生構造函數模式同樣,這樣建立出來的對象與構造函數之間沒有什麼關係,instanceof操做符對他們沒有意義。

相關文章
相關標籤/搜索