ECMAScript创建对象1 —— Object()、工厂模式、构造函数模式

使用Object构造函数或对象字面量

在JavaScript中,我们可以很轻松的通过如下方式创建一个对象

var obj1 = new Object();
obj1.proto1 = 'proto1'; // 使用Object构造函数

var obj2 = {
    proto2: 'proto2'
} // 使用对象字面量

这两种方式都能很直观简单地帮助我们创建一个新的对象,但这两种方法也有很明显的缺点:每一个对象都需要我们不停地给它添加属性,即使是创建两个具有相同属性的对象,这会产生大量的重复代码。

工厂模式

工厂模式应该是最广为人知的一种设计模式了,它抽象了创建对象的具体过程,解决了重复代码的问题。由于ECMAScript中没有类的概念,所以只能使用函数来封装创建对象的细节。如:

function createObj (name, age) {
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    return obj
}

var obj1 = createObj('a', 10); // {name: 'a', age: 10}
var obj2 = createObj('b', 11); // {name: 'b', age: 11}

工厂模式虽然解决了重复代码的问题,但它创建的对象的类型都是Object:

obj1 instanceof createObj  // false
obj1 instanceof Object  // true

构造函数模式

我们可以使用Array、Object等构造函数来创建我们需要的对象,我们也可以自定义一个构造函数来创建一个自定义类型的对象。构造函数并不是什么特殊的函数,任何函数使用new关键字调用都能作为构造函数,只是有一个惯例,构造函数的函数名始终以大写字母开头

相比于工厂模式,构造函数的代码有了几点不同:

  • 没有显式地创建的对象(var obj = new Object() 语句)
  • 将需要的属性和方法都赋给了this对象
  • 没有return

上面的代码可以重写如下:

function CreateObj (name, age) {
    this.name = name;
    this.age = age;
    this.sayName = function () {
        console.log(this.name);
    }
}

var obj1 = new CreateObj('a', 10); // {name: 'a', age: 10}
var obj2 = new CreateObj('b', 11); // {name: 'b', age: 11}
CreateObj('c', 12); // {name: 'c', age: 12}
obj1 instanceof CreateObj // true
obj1 instanceof Object // true
obj1.sayName == obj2.sayName // false

构造函数让每个实例都拥有了特定的类型,但这种模式也有缺点:

由于ECMAScript中函数也是对象,所以对于不同的CreateObj实例,它们的sayName属性就是互不相等但功能完全相同的函数对象,实在没有必要;况且,既然有了this的存在,sayName属性完全可以采用下面的写法:

function CreateObj (name, age) {
    this.name = name;
    this.age = age;
    this.sayName = sayName;
}
function sayName = function () {
    console.log(this.name);
}

在全局中创建的sayName函数能够解决创建多个功能相同的函数的问题,但是它的问题在于只有CreateObj实例能正确使用它,这样就失去了全局函数的意义,这也在对象只需要一个方法的情况下,如果需要很多方法,就需要创建很多的只能特定对象调用的全局函数,毫无封装性可言。

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