天天看點

007-js建立對象的幾種方式

1.字面量方式建立

var person = {
    name: 'James',
    age: 20,
    say: function() {
        console.log(this.name);
    }
}
           

此種方式缺點:建立很多對象的時候,會産生很多重複代碼

2.工廠模式

為了解決重複代碼的問題,使用工廠模式建立對象

function createPerson(name, age) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.say = function() {
        console.log(this.name);
    }
    return o;
}

var person1 = createPerson('James', 20);
var person2 = createPerson('Jack', 23);

person1.say();
person2.say();
           

工廠模式雖然解決了代碼重複的問題,但是又有新的問題了,就是對象識别的問題,因為這些對象都來自我們new出來的

Object

。下面的一種模式就解決了這個問題

3.構造函數模式

function Person(name, age) {
    this.name = name;
    this.age = age;
    this.say = function() {
        console.log(this.name)
    }
} 

var person1 = new Person('James', 20);
var person2 = new Person('Jack', 23);

person1.say();
person2.say();
           

之前我們說了,工廠模式無法解決對象識别的問題,那麼構造函數模式是否解決了呢,我們驗證一下

console.log(person1 instanceof Person);  // true
console.log(person2 instanceof Person);  // true
           

由此可見,對象識别是成功了的!

我們觀察發現這種模式跟第二種工廠模式很類似,但是也有些差別:

  • 在Person裡并沒有建立對象
  • 使用new

那麼到底發生了什麼呢?

4.原型模式

什麼是原型,請看008-JS原型和原型鍊

使用原型對象的好處是可以讓所有對象執行個體共享它包含的屬性和方法。我們不需要在構造函數中添加屬性和方法,這些東西一股腦都放到原型中。

function Person() {}

Person.prototype = {
    name: 'James',
    age: 20,
    say: function() {
        console.log(this.name)
    }
}

var person = new Person();
person.say();
           

原型模式也是有缺點的:

  • 原型的屬性的值被定義為固定值,那麼所有執行個體的屬性的值都會成為固定值
  • 原型的屬性為引用類型的時候,容易導緻篡改屬性
function Person() {}

Person.prototype = {
    friends: ['Jack', 'Tom']
}

var person1 = new Person();
var person2 = new Person();
person1.friends.push('Teddy');
console.log(person2.friends);  // [ 'Jack', 'Tom', 'Teddy' ]
           

我們發現,執行個體person1的數組friends改變之後,執行個體person2的friends也被改變了

為了解決這個問題,有了組合使用構造函數模式和原型模式

5.組合使用構造函數模式和原型模式

所謂組合使用構造函數模式和原型模式,就是拿出兩種模式的優點,創造出一種新的模式。

function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.say = function() {
    console.log(this.name);
}

var person1 = new Person('James', 20);
var person2 = new Person('Jack', 23);

person1.say();
person2.say();
           

在此種模式中,我們把屬性放在構造函數中,把方法放在原型中。這樣既能保證執行個體可以傳入屬性,又能確定方法可以共享,一舉兩得。這也是目前使用最多的一種模式。

6.動态原型模式

function Person(name, age) {
    this.name = name;
    this.age = age;

    if(typeof this.say != 'function') {
        Person.prototype.say = function() {
            console.log(this.name);
        }
    }
}

var person = new Person('James', 20);
person.say()
           

參考:《JavaScript進階程式設計》

繼續閱讀