• 主页
  • github
  • 简历

JavaScript中各种创建对象方法的优缺点

  1. 工厂模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    function createPerson(name, age) {
    var person = new Object();
    person.name = name;
    person.age = age;
    person.sayName = function () {
    console.log(this.name);
    };
    return person;
    }
    var person = createPerson('a', 11);
    person.sayName();

    工厂模式为创建大量同类对象提供了方便, 但是有着对象识别的问题, 即怎么知道一个对象的类型.

  2. 构造函数模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    function Person(name, age) {
    this.name = name;
    this.age = age;
    this.sayName = function() {
    console.log(this.name);
    };
    }
    var person = new Person('a', 11);
    person.sayName();

    构造函数模式创建的对象共用相同的构造函数(constructor), 可以使用instanceof操作判断类型. 需要通过new操作符创建对象, 否则this会指向全局作用域. 构造函数中定义的对象方法是不同的Function实例, 即person1.sayName !== person2.sayName. 可以将sayName定义在全局, 然后在构造函数中使用 this.sayName = sayName, 这样子每个对象实例会共享方法, 但是同时在全局作用域留下了额外的函数.

  3. 原型模式

    1
    2
    3
    4
    5
    6
    7
    8
    function Person() { }
    Person.prototype.name = 'a';
    Person.prototype.age = 11;
    Person.prototype.sayName = function () {
    console.log(this.name);
    };
    var person = new Person('a', 11);
    person.sayName();

    原型模式中定义属性会被所有实例共享, 修改person1.name不会影响person2.name的值, 但是修改Person.prototype.name会影响所有Person对象实例.

  4. 简化的原型模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function Person() { }
    Person.prototype = {
    name: 'a',
    age: 11,
    sayName: function () {
    console.log(this.name);
    }
    };
    var person = new Person('a', 11);
    person.sayName();

    简化的原型模式可以省去每次都要敲一遍的Person.prototype, 但是constructor不再指向Person的constructor了. 可以添加额外属性constructor: Person.constructor使其构造constructor仍指向Person的constructor. 但是此时的constructor是可枚举的, 而原来的constructor并不可枚举.

  5. 组合使用构造函数模式和原型模式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function Person(name, age) {
    this.name = name;
    this.age = age;
    this.friends = ['ezreal', 'ashe'];
    }
    Person.prototype = {
    constructor: Person.constructor,
    sayName: function() {
    console.log(this.name);
    }
    };
    var person = new Person('a', 11);
    person.sayName();

    这种模式中, 实例属性在构造函数中定义, 共享属性则是在原型中定义, 修改person1.friends并不会影响person2.friends. 本模式是最广泛, 认可度最高的一种创建自定义类的方法.