JavaScript创建对象的四种方式详解:工厂、构造函数、原型及组合模式
本文详细解析JavaScript中创建对象的四种核心方式:工厂模式、构造函数模式、原型模式以及组合使用模式。通过对比每种模式的优缺点,如对象识别、内存占用及属性共享等问题,帮助开发者根据实际需求选择最合适的对象创建策略,并提供相应的代码示例与最佳实践建议。
JavaScript对象创建概述
前言
在JavaScript中,创建对象的方法多种多样。本文将系统梳理其中四种常见的方式,并逐一分析各自的优缺点,以便开发者能够根据具体场景做出合理选择。
工厂模式
工厂模式
function createPerson(name, age){
var obj = new Object();
obj.name = name;
obj.age = age;
return obj; //一定要返回,否则打印undefined:undefined
}
var person1 = new createPerson('Young',18);
console.log(person1.name + ':' + person1.age);
该模式的主要优势在于能够有效解决创建多个相似对象的问题,通过封装创建逻辑简化实例化过程。
然而,其局限性在于无法解决对象识别问题,即难以通过实例直接判断其所属的具体类型。
构造函数模式
构造函数模式
function Person(name,age){
this.name = name;
this.age = age;
}
var person1 = new Person('Young',18);
console.log(person1.name + ':' + person1.age);
在探讨其优缺点之前,我们先了解该模式的一些基本特性与使用场景。
将构造函数当做函数使用
function Person(name,age){
this.name=name;
this.age=age;
this.sayName=function(){
return this.name;
}
}
//当做构造函数使用
var person1 = new Person('Young', 18);
person1.sayName();
console.log(person1.name + ':' + person1.age);
//当做普通函数调用
Person('Wind', 18);
console.log(window.sayName());
//在另一个作用域中调用
var obj = new Object();
Person.call(obj, 'bird', 100);
console.log(obj.sayName());
构造函数优缺点
其优点在于,通过实例可以明确标识出特定的类型,增强了代码的可读性与类型安全性。
缺点在于,每个方法都会在实例上重新创建一遍,导致内存浪费。当然,可以通过以下方式优化:
function Person(name, age){
this.name = name;
this.age = age;
this.sayName = sayName;
}
function sayName(){
return this.name;
}
若改为调用全局函数,虽然解决了内存问题,却牺牲了封装性。接下来的原型模式可以弥补这一不足。
原型模式
原型模式
function Person(){
}
Person.prototype.name = 'Young';
Person.prototype.age = 18;
Person.prototype.sayName = function(){
return this.name;
}
var person1 = new Person();
console.log(person1.sayName());
var person2 = new Person();
console.log(person1.sayName());
alert(person1.sayName === person2.sayName);
//person1和person2访问的是同一组属性的同一个sayName()函数
虽然可以通过对象实例访问保存在原型中的值,但不能通过实例对象直接重写原型中的值。
function Person(){
}
Person.prototype.name='Young';
Person.prototype.age=18;
Person.prototype.sayName=function(){
return this.name;
}
var person1=new Person();
var person2=new Person();
person1.name='Wind';
console.log(person1.sayName());//Wind
console.log(person2.sayName());//Young
alert(person1.sayName==person2.sayName);//true
在我们调用person1.sayName的时候,会先后执行两次搜索,解析器先确定实例person1是否有sayName的属性,有则调用自己的属性,没有则搜索原型中的属性。
function Person(){
}
Person.prototype.name='Young';
Person.prototype.age=18;
Person.prototype.sayName=function(){
return this.name;
}
var person1=new Person();
var person2=new Person();
person1.name='Wind';
console.log(person1.sayName());//Wind
console.log(person2.sayName());//Young
delete person1.name;
console.log(person1.sayName());//Young
console.log(person2.sayName());//Young
使用hasOwnPropertyType方法可以检测一个属性是存在与原型中还是存在于实例中,该方法是从Object继承来的,实例中为true,原型中为false。
枚举对象上的实例属性用Object.keys()方法
function Person(){
}
Person.prototype.name='Young';
Person.prototype.age=18;
Person.prototype.sayName=function(){
return this.name;
}
var keys=Object.keys(Person.prototype);
console.log(keys);//["name", "age", "sayName"]
原型模式优缺点
优点:不用每个方法都要在每个实例上重申一遍,节省了内存空间。
缺点:很少有人单独使用原型模式地。。问题详列
function Person(){
}
Person.prototype={
constructor:Person,
name:'Young',
age:18,
friends:['Big','Pig'],
sayName:function(){
return this.name;
}
};
var p1=new Person();
var p2=new Person();
p1.friends.push('Mon');
console.log(p1.friends);//["Big", "Pig", "Mon"]
console.log(p2.friends);//["Big", "Pig", "Mon"]
正是因为实例一般都要有自己的属性,而我们这里将他放在了Person.prototype中,所以随着p1的修改,整个实例包括原型都修改了。那么,我们可以组合使用构造函数模式和原型模式。
组合模式
组合使用构造函数模式和原型模式
function Person(name,age){
this.name=name;
this.age=age;
this.friends=['Big','Pig'];
}
Person.prototype={
sayName:function(){
return this.name;
}
};
var p1=new Person('Young',18);
var p2=new Person('Wind',78);
p1.friends.push('Raganya');
console.log(p1.friends);//["Big", "Pig", "Raganya"]
console.log(p2.friends);//["Big", "Pig"]
console.log(p1.friends==p2.friends);//false
console.log(p1.sayName==p2.sayName);//true
这种模式是目前使用最广泛、认同度最高的一种创建自定义类型的方法。是用来定义引用类型的一种默认模式。
总结
以上就是关于分析Javascript中创建对象方式的全部内容,通过这篇文章为大家总结的四种方式和其优缺点,希望可以对大家学习使用Javascript能有所帮助。
ES6模块化中js文件怎么用import和export交互
2026-11-05 17:00:48
JS读取本地文件时报错或无响应的常见原因
2026-11-05 16:32:31
let、const与var的区别:JavaScript变量声明最佳实践
2026-11-05 14:16:38
JS中直接定义静态二维数组的字面量写法
2026-11-05 14:16:08
JS 怎么查找字符串中所有匹配项的位置
2026-11-05 14:15:53
