JavaScript高級程序設計創建對象方法總結

工廠模式

function Person() {
  var o = new Object();
  o.name = 'hanmeimei';
  o.say = function() {
    alert(this.name);
  }
  return o;
}
var person1 = Person();

優點:

  • 簡單易懂。

缺點:

  • 無法通過constructor識別對象,以爲都是來自Object,無法得知來自Person
  • 每次通過Person創建對象的時候,所有的say方法都是一樣的,但是卻存儲了多次,浪費資源。

構造函數模式

function Person() {
  this.name = 'hanmeimei';
  this.say = function() {
    alert(this.name)
  }
}
var person1 = new Person();

優點:

  • 通過constructor或者instanceof可以識別對象實例的類別
  • 可以通過new 關鍵字來創建對象實例,更像OO語言中創建對象實例

缺點:

  • 多個實例的say方法都是實現一樣的效果,但是卻存儲了很多次(兩個對象實例的say方法是不同的,因爲存放的地址不同)

注意:

  • 構造函數模式隱試的在最後返回return this 所以在缺少new的情況下,會將屬性和方法添加給全局對象,瀏覽器端就會添給window對象。
  • 也可以根據return this 的特性調用call或者apply指定this。這一點在後面的繼承有很大幫助。

原型模式

function Person() {}
Person.prototype.name = 'hanmeimei';
Person.prototype.say = function() {
  alert(this.name);
}
Person.prototype.friends = ['lilei'];
var person1 = new Person();

優點:

  • say方法是共享的了,所有的實例的say方法都指向同一個。
  • 可以動態的添加原型對象的方法和屬性,並直接反映在對象實例上。
var person1 = new Person()
Person.prototype.showFriends = function() {
  console.log(this.friends)
}
person1.showFriends()  //['lilei']

缺點:

1.出現引用的情況下會出現問題具體見下面代碼:

var person1 = new Person();
var person2 = new Person();
person1.friends.push('xiaoming');
console.log(person2.friends)  //['lilei', 'xiaoming']

因爲js對引用類型的賦值都是將地址存儲在變量中,所以person1和person2的friends屬性指向的是同一塊存儲區域。

2.第一次調用say方法或者name屬性的時候會搜索兩次,第一次是在實例上尋找say方法,沒有找到就去原型對象(Person.prototype)上找say方法,找到後就會在實力上添加這些方法or屬性。
3.所有的方法都是共享的,沒有辦法創建實例自己的屬性和方法,也沒有辦法像構造函數那樣傳遞參數。

注意:

優點②中存在一個問題就是直接通過對象字面量給Person.prototype進行賦值的時候會導致constructor改變,所以需要手動設置,其次就是通過對象字面量給Person.prototype進行賦值,會無法作用在之前創建的對象實例上

    var person1 = new Person()
    Person.prototype = {
        name: 'hanmeimei2',
          setName: function(name){
          this.name = name
          }
    }
    person1.setName()   //Uncaught TypeError: person1.set is not a function(…)

這是因爲對象實例和對象原型直接是通過一個指針鏈接的,這個指針是一個內部屬性[[Prototype]],可以通過__proto__訪問。我們通過對象字面量修改了Person.prototype指向的地址,然而對象實例的__proto__,並沒有跟着一起更新,所以這就導致,實例還訪問着原來的Person.prototype,所以建議不要通過這種方式去改變Person.prototype屬性

動態原型模式

function Person(name) {
  this.name = name
  if(typeof this.say != 'function') {
    Person.prototype.say = function(
    alert(this.name)
  }
}
var friend = new Person("jjc")
friend.say()

構造函數和原型組合模式

function Person(name) {
  this.name = name
  this.friends = ['lilei']
}
Person.prototype.say = function() {
  console.log(this.name)
}
var person1 = new Person('hanmeimei')
person1.say() //hanmeimei

優點:

  • 解決了原型模式對於引用對象的缺點
  • 解決了原型模式沒有辦法傳遞參數的缺點
  • 解決了構造函數模式不能共享方法的缺點

寄生構造函數模式

function Person(name) {
  var o = new Object()
  o.name = name
  o.say = function() {
    alert(this.name)
  }
  return o
}
var peron1 = new Person('hanmeimei')

穩妥構造模式

function Person(name) {
  var o = new Object()
  o.say = function() {
    alert(name)
  }
}
var person1 = new Person('hanmeimei');
person1.name  // undefined
person1.say() //hanmeimei

優點:

  • 安全,那麼好像成爲了私有變量,只能通過say方法去訪問
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章