JavaScript构造函数模式详解与优化
本文深入解析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);
} 这样解决了两个函数做同一件事情的问题,但是新的问题又会出现了,这个在全局作用域中定义的函数,实际上只能被某个对象引用,而且最要命的问题是,如果对象需要定义很多方法,那么就需要定义很多个全局函数,所以这个自定义的引用类型,就没有任何封装性可言了.
JS语法错误会阻止加载吗?区分SyntaxError与资源加载失败
2026-11-05 16:08:46
JavaScript常见SyntaxError语法错误排查与修复方法
2026-11-05 13:58:44
JS中slice、substring和substr截取字符串的区别
2026-11-05 13:43:47
JS 转 TS 手动迁移最佳实践:从配置 tsconfig 到消除 any 类型
2026-11-05 11:53:32
为什么JS数组push后得到的是数字而不是数组?
2026-11-05 09:59:18
