JavaScript中創建對象的方法(中)

  我們在上篇說到了工廠模式和構造函數模式,結尾說到解決構造函數模式的缺點的方法是引入了原型模式,本篇就來說說原型模式及其與構造函數模式的組合使用。

一、原型模式

    首先要理解:我們創建的每一個函數都有一個prototype(原型)屬性,該屬性是一個指針,指向一個對象,該對象的用途就是包含特定類型所有實例共享的屬性和方法。
    舉個例子: 我們定義一個構造函數Person;那麼他的prototype屬性所指的對象包含着所有Person的實例所共享的屬性和方法;且該對象就是Person所有實例的原型對象
    使用原型的好處是:所有實例可以共享原型對象中的屬性和方法;舉例如下:
    function Person() {
    }
    Person.prototype.name = 'Jack';
    Person.prototype.friends = ['Lily', 'John'];
    var person1 = new Person();
    var person2 = new Person();
    console.log(person1.name);//Jack
    console.log(person2.name);//Jack

   由於person1和person2都是Person的實例,所以都能訪問他們共同的原型對象上的name屬性。

   然而,原型模式也有缺點,繼續上邊的代碼執行以下代碼:

    person1.friends.push('Lucy');
    console.log(person1.friends);//["Lily", "John", "Lucy"]
    console.log(person2.friends);//["Lily", "John", "Lucy"]

   由於friends屬性定義在原型對象上,所以一旦改變,所有實例都會改變,顯然實際中這不是我們期望的,我們希望各自的friends屬性互不影響;爲解決這一問題,我們採用了原型模式和構造函數的組合使用;

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

    繼續上邊的例子,我們將實例需要獨自擁有的屬性或方法定義在構造函數裏邊,將共享的屬性或者方法定義在原型對象中,舉例如下:

    function Person(name) {
        this.name=name;
        this.friends=['Jack'];
    }
    Person.prototype.sayName=function(){
        console.log(this.name);
    };
    var person1 = new Person('Alice');
    var person2 = new Person('Bob');
    person1.sayName();//Alice
    person2.sayName();//Bob

    person1.friends.push('Lucy');
    console.log(person1.friends);//["Jack", "Lucy"]
    console.log(person2.friends);//["Jack"]

    可以看到,構造函數裏邊的name和friends屬性各實例分別擁有自己的一份,不會互相干擾,sayName方法所有實例共享。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章