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方法所有实例共享。


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