創(chuàng)建對(duì)象的幾種方法

1. 工廠模式

用接口來(lái)封裝以特定接口來(lái)創(chuàng)建對(duì)象的細(xì)節(jié)
// 缺點(diǎn):對(duì)象無(wú)法識(shí)別,因?yàn)樗械膶?shí)例都指向一個(gè)原型

var log = console.log.bind(console)
function creatPerson(name) {
  var o = new Object()
  o.name = name
  o.getName = function () {
     console.log(this.name);
   };
   return o
}
var person = creatPerson('haha')
var person1 = creatPerson('haha')
log(1111, person.__proto__)  //都是指向Object
log(2222, person1.__proto__)  //都是指向Object

2.構(gòu)造函數(shù)模式

// 優(yōu)點(diǎn):實(shí)例可以識(shí)別為一個(gè)特定的類(lèi)型
// 缺點(diǎn):每次創(chuàng)建實(shí)例時(shí),每個(gè)方法都要被創(chuàng)建一次

var log = console.log.bind(console)
function Person(name) {
  this.name = name
  this.getName = function() {
    log(this.name)
  }
}
var person2 = new Person('meimei')
var person3 = new Person('meimei1')
log(person2.name)  //meimei
//這里指向的是Person,但是每次創(chuàng)建實(shí)例,函數(shù)也會(huì)被創(chuàng)建一次
log(3333, person2.__proto__.constructor.name)  
log(person2.getName == person3.getName)  //false

2.1優(yōu)化構(gòu)造函數(shù)模式

優(yōu)點(diǎn):解決了每個(gè)方法都要被重新創(chuàng)建的問(wèn)題
缺點(diǎn):這叫啥封裝……

var log = console.log.bind(console)
function Person1(name) {
    this.name = name;
    this.getName = getName;
}
// 放在外面調(diào)用,可以避免上面的重復(fù)創(chuàng)建問(wèn)題
function getName() {
    console.log(this.name);
}
var person4 = new Person1('kevin');
var person5 = new Person1('kevin1');
log(4444, person4.__proto__.constructor.name)   //指向"Person1"
log(person4.getName == person5.getName)  //true

3.原型模式

// 優(yōu)點(diǎn):方法不會(huì)重新創(chuàng)建
// 缺點(diǎn):1. 所有的屬性和方法都共享 2. 不能初始化參數(shù)

var log = console.log.bind(console)
function Person2() {}
// 無(wú)法初始化這個(gè)name值
Person2.prototype.name = 'hah'
Person2.prototype.getName = function(){
    console.log(this.name);
}
var person6 = new Person2();  //無(wú)法改變name 的值
log(5555, person6.__proto__.constructor.name)  //指向"Person2"

3.1優(yōu)化原型模式

// 優(yōu)點(diǎn):封裝性好了一點(diǎn), 實(shí)例可以通過(guò)constructor屬性找到所屬構(gòu)造函數(shù)
// 缺點(diǎn):重寫(xiě)了原型, 原型模式該有的缺點(diǎn)還是有

var log = console.log.bind(console)
function Person3() {}
Person3.prototype = {
  coustructor: Person3,
  name: 'hah',
  getName: function(){
     console.log(this.name);
  }
}
var person7 = new Person3();  //無(wú)法改變name 的值
log(6666, person7.__proto__.coustructor.name)  //指向"Person3"

4.組合使用構(gòu)造函數(shù)模式和原型模式

// 優(yōu)點(diǎn):該共享的共享,該私有的私有,使用最廣泛的方式
// 缺點(diǎn):有的人就是希望全部都寫(xiě)在一起,即更好的封裝性

var log = console.log.bind(console)
function Person4(name) {
  this.name = name
}
Person4.prototype.getName = function(){
    console.log(this.name);
}
var person8 = new Person4('haha'); 
log(7777, person8.__proto__.constructor.name)  //指向"Person4"

4.1動(dòng)態(tài)原型模式

var log = console.log.bind(console)
function Person5(name) {
  this.name = name
  if(typeof this.getName != 'function') {
    // 注意:使用動(dòng)態(tài)原型模式時(shí),不能用對(duì)象字面量重寫(xiě)原型
    Person5.prototype.getName = function() {
      log(this.name)
    }
  }
}
var person9 = new Person5('meimei')
log(8888, person9.__proto__.constructor.name)  //指向"Person5"

5.1寄生構(gòu)造函數(shù)模式

// 寄生-構(gòu)造函數(shù)-模式,也就是說(shuō)寄生在構(gòu)造函數(shù)的一種方法。
// 缺點(diǎn):創(chuàng)建的實(shí)例使用 instanceof 都無(wú)法指向構(gòu)造函數(shù)
// 特殊情況下可使用,如果想創(chuàng)建一個(gè)具有額外方法的特殊數(shù)組,但又不想直接修改Array構(gòu)造函數(shù)

var log = console.log.bind(console)
function Person6(name) {
  var o = new Object()  
  o.name = name
  o.getName = function() {
    log(this.name)
  }
  return o
}
var person10 = new Person6('meimei') //比工廠模式多了一個(gè)new,實(shí)際上2者的結(jié)果是一樣的
console.log(person10 instanceof Person) // false
console.log(person10 instanceof Object)  // true
log(9999, person10.__proto__.constructor.name)  //指向Object

5.2穩(wěn)妥構(gòu)造函數(shù)模式

// 與寄生構(gòu)造函數(shù)模式有兩點(diǎn)不同:
// 1)新創(chuàng)建的實(shí)例方法不引用 this
// 2)不使用 new 操作符調(diào)用構(gòu)造函數(shù)
// 穩(wěn)妥對(duì)象最適合在一些安全的環(huán)境中。
// 穩(wěn)妥構(gòu)造函數(shù)模式也跟工廠模式一樣,無(wú)法識(shí)別對(duì)象所屬類(lèi)型。

var log = console.log.bind(console)
function Person7(name){
    var o = new Object();
    o.sayName = function(){
        console.log(name);
    };
    return o;
}

var person11 = Person7('kevin');
person11.sayName(); // kevin
person11.name = "daisy";
person11.sayName(); // kevin
console.log(person11.name); // daisy
log(1000, person11.__proto__.constructor.name)  //指向Object

詳見(jiàn):查看效果

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容