面向对象(创建对象)--构造函数模式02

上一篇工厂模式中有一个例子

面向对象(创建对象)--构造函数模式02

现在创建自定义的构造函数,从而定义自定义对象类型的属性和方法。例如,可以使用构造函数模式将上面的例子重写如下 

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function () {
        alert(this.name);
    };
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor"); 

比较会发现3个不同之处

 

要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。

  1. 没有显式地创建
  2. 直接将属性和方法赋给了 this 对象
  3. 没有 return 语句

优点: 创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。也就是说,在这个例子中,我们可以知道person1 和 person2 是Object 的实例。

1.将构造函数当做函数
构造函数与其他函数的唯一区别,就在于调用它们的方式不同。例如,前面例子中定义的 Person()函数可以通过下列任何一种方式来调用。
// 当作构造函数使用
var person = new Person("Nicholas", 29, "Software Engineer"); 
person.sayName(); //"Nicholas" 
// 作为普通函数调用
Person("Greg", 27, "Doctor"); // 添加到 window 
window.sayName(); //"Greg" 
// 在另一个对象的作用域中调用
var o = new Object(); 
Person.call(o, "Kristen", 25, "Nurse"); 
o.sayName(); //"Kristen" 
2.构造函数的问题
在前面的例子中,person1 和 person2 都有一个名为 sayName()的方法,但那两个方法不是同一个 Function 的实例。然而,创建两个完成同样任务的 Function 实例的确没有必要;况且有 this 对象在,根本不用在执行代码前就把函数绑定到特定对象上面。因此,大可像下面这样,通过把函数定义转移到构造函数外部来解决这个问题。
function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = sayName;
}
function sayName() {
    alert(this.name);
}
var person1 = new Person("Nicholas", 29, "Software Engineer");
var person2 = new Person("Greg", 27, "Doctor"); 

可是新问题又来了:在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域有点名不副实。而更让人无法接受的是:如果对象需要定义很多方法,那么就要定义很多个全局函数,于是我们这个自定义的引用类型就丝毫没有封装性可言了。