JavaScript构造函数模式详解与优化

作者:小括号时间:2026-10-26 16:13:42浏览:594

本文深入解析JavaScript中的构造函数模式,对比其与工厂模式的差异,详细说明实例创建的四步过程及类型判断方法。同时探讨构造函数作为普通函数调用的灵活性,并针对每个实例重复创建方法导致的内存浪费问题,提出将函数定义移至全局作用域以优化封装性的解决方案。

构造函数模式重构工厂模式

接下来,我们将采用构造函数模式对前文提到的工厂模式进行重构。


具体实现代码如下:

 
function Employee(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function () {
alert(this.name);
}; 
} 
var Jim = new Employee("jim", 22, "SoftWare Engineer");
var Sun = new Employee("Sun", 24, "Doctor");
Jim.sayName();
Sun.sayName();

在上述代码中,Employee函数替代了原有的CreateEmployee函数。对比两者,Employee函数的实现有显著不同:


不再显式地创建对象。


直接将属性和方法赋值给this对象。


省略了return语句。


若要创建Employee类的新实例,必须使用new操作符,该过程实际包含四个步骤:


创建一个新对象。


将构造函数的作用域赋给这个新对象(即this指向该对象)。


执行构造函数中的代码。


返回新创建的对象。


执行上述代码后,Jim和Sun分别保存了Employee的两个不同实例。这两个实例都拥有一个constructor属性,该属性指向Employee构造函数。我们可以通过以下方式验证:


具体测试代码如下:

 
alert(Jim instanceof Employee); //true
alert(Sun instanceof Employee);//true

此外,由于所有对象最终都继承自Object,因此这两个对象同样属于Object类型,可通过以下代码进行验证。


验证代码如下:

 
alert(Jim instanceof Object); //true
alert(Sun instanceof Object);//true

定义自定义构造函数的意义在于,未来可以将其实例标识为特定的类型,这正是构造函数模式优于工厂模式的关键所在。


构造函数的调用方式与问题

下面详细解析构造函数的使用细节:


将构造函数视为普通函数


构造函数与其他函数的唯一区别在于调用方式不同。实际上,构造函数也是函数,并没有定义构造函数的特殊语法。任何函数,只要通过new来调用,就可以作为构造函数。例如,除了使用new调用Employee外,还可以采用以下方式调用。


示例代码如下:

 
//作为普通函数调用
Employee("Sun", 28, "SoftWare Engineer"); //添加到window中
window.sayName();//Sun

另一种调用方式如下:

//在另一个对象的作用域中调用
var o = new Object();
Employee.call(o, "Sun", 28, "SoftWare Engineer");
o.sayName();//Sum

构造函数模式存在一个主要问题:每个实例都会重新创建一遍方法。以上两个对象中的sayName方法实际上是不同的Function实例,可以通过以下方式证明:


验证代码如下:


alert(Jim.sayName == Sun.sayName);//false


既然创建两个完成同样任务的Function实例并无必要,我们可以对上面的函数进行改写,如下所示。


改写后的代码如下:

 
function Employee(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName =sayName;
} 
function sayName() {
alert(this.name);
} 

这样解决了两个函数做同一件事情的问题,但是新的问题又会出现了,这个在全局作用域中定义的函数,实际上只能被某个对象引用,而且最要命的问题是,如果对象需要定义很多方法,那么就需要定义很多个全局函数,所以这个自定义的引用类型,就没有任何封装性可言了.

作者最新文章