JS之稳妥构造函数模式and静态私有变量

本文介绍了JavaScript中稳妥构造函数的实现原理及其特点,包括如何通过闭包实现私有变量,以及静态私有变量的概念和应用示例。
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>稳妥构造函数and静态私有变量的实现原理</title>
</head>
<body>
<script type="text/javascript">
//test 稳妥构造函数或者叫做JS中私有变量的实现
function Person(name, age, job) {
	var o = new Object();
	
	o.sayName = function() {
		console.log(name);
	};

	o.setName = function(value) {
		name = value;
	};

	return o;
};

var friend = Person("Nicholas", 29, "Soft Engineer");
/*
	稳妥构造函数特点:属性只能通过方法来访问,直接访问不到。
	稳妥构造函数原理:利用了闭包函数在定义时其作用域链不光包含了全局变量对象还包含了外部函数的变量对象。所以在执行闭包函数sayName时,就可以通过外部函数变量对象找到name属性的值
	而直接访问name属性,由于friend对象中并没有这个属性,所以是undifined;
	原理详见《javascript高级程序设计》电子版7.2节《闭包》的内容
*/
friend.sayName(); //sayName和setName又被称为特权方法
console.log(friend.name);//undifined

//test 静态私有变量
/*
    静态私有变量顾名思义:1:首先这个变量是静态的,所有的对象访问的都是同一个对象。2:这个静态变量是私有的,只能通过特权方法来访问。
*/
(function(){
	var name = "";
	//注意这里的Student并没有使用var关键字,这样做的目的是让这个构造函数成为一个全局的变量,这样才可以在函数外访问。
	Student = function(value) {name = value};

	Student.prototype.getName = function() { return name;};

	Student.prototype.setName = function(value) { name = value};

})();//注意这是一个函数表达式而不是一个函数声明。

var stu1 = new Student("bobo");
console.log(stu1.getName()); //bobo
var stu2 = new Student("Grey");
console.log(stu1.getName()); //Grey(说明静态变量确实被stu2对象修改了)
</script>
</body>
</html>

<think>我们正在处理用户关于JavaScript创建对象的不同设计模式的问题。用户希望了解工厂模式构造函数模式、原型模式、组合模式、动态原型模式、寄生构造函数模式稳妥构造函数模式。我们将参考提供的引用材料,并按照要求进行回答。 要求: 1. 行内数学表达式使用$...$(但本问题中可能不涉及数学表达式,但如果有变量等,我们会注意) 2. 独立公式使用$$...$$(同样,本问题可能不涉及) 3. 使用中文回答 4. 生成相关问题 5. 回答中引用的段落末尾添引用标识,例如[^1] 由于用户的问题是关于JavaScript对象创建模式,我们将逐一解释每种模式,并给出代码示例。注意,引用材料中提供了部分模式的代码和说明,我们将参考这些内容。 结构: 1. 工厂模式 2. 构造函数模式 3. 原型模式 4. 组合模式(组合使用构造函数模式和原型模式) 5. 动态原型模式 6. 寄生构造函数模式 7. 稳妥构造函数模式 每种模式包括: - 定义 - 代码示例 - 优缺点 最后,生成相关问题。 开始回答:</think>### JavaScript 创建对象的设计模式详解 #### 1. **工厂模式** 通过函数封装对象创建过程,返回新对象。 **示例**: ```javascript function createPerson(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); }; return o; } var person1 = createPerson("Nicholas", 29, "Software Engineer"); ``` **优点**:代码复用,隐藏创建细节。 **缺点**:无法识别对象类型(`instanceof` 只能检测到 `Object`)。 **适用场景**:需批量创建相似对象但无需类型检查时[^2]。 --- #### 2. **构造函数模式** 使用 `new` 调用构造函数,`this` 绑定到新对象。 **示例**: ```javascript function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = function() { alert(this.name); }; } var person1 = new Person("Greg", 27, "Doctor"); ``` **优点**:可识别对象类型(`person1 instanceof Person === true`)。 **缺点**:方法需在每个实例上重复创建,浪费内存(`person1.sayName !== person2.sayName`)[^3]。 --- #### 3. **原型模式** 利用 `prototype` 共享属性和方法。 **示例**: ```javascript function Person() {} Person.prototype.name = "Nicholas"; Person.prototype.sayName = function() { alert(this.name); }; var person1 = new Person(); ``` **优点**:所有实例共享方法,节省内存。 **缺点**: - 引用类型属性被所有实例共享(如数组修改会互相影响)。 - 无法通过构造函数传递初始化参数[^4]。 --- #### 4. **组合模式(最常用)** **构造函数定义实例属性** + **原型定义共享方法**。 **示例**: ```javascript function Person(name, age) { this.name = name; // 实例属性 this.age = age; this.friends = ["1", "2"]; } Person.prototype.sayName = function() { alert(this.name); }; // 共享方法 var person1 = new Person("Joker", 23); ``` **优点**: - 实例属性独立(`person1.friends.push("3")` 不影响 `person2`)。 - 方法共享(`person1.sayName === person2.sayName`)。 **适用场景**:ECMAScript 默认推荐模式[^1][^3]。 --- #### 5. **动态原型模式** 在构造函数内部**按需初始化原型**。 **示例**: ```javascript function Person(name, age, job) { this.name = name; this.age = age; this.job = job; // 仅当方法不存在时初始化原型 if (typeof this.sayName !== "function") { Person.prototype.sayName = function() { alert(this.name); }; } } var friend = new Person("Nicholas", 29, "Software Engineer"); ``` **优点**: - 保持组合模式优点的同时,封装更彻底。 - 避免多次初始化原型[^1]。 --- #### 6. **寄生构造函数模式** 类似工厂模式,但使用 `new` 调用。 **示例**: ```javascript function SpecialArray() { var values = new Array(); values.push.apply(values, arguments); values.toPipedString = function() { return this.join("|"); }; return values; // 覆盖默认返回的实例 } var colors = new SpecialArray("red", "blue"); colors.toPipedString(); // "red|blue" ``` **特点**: - 返回的对象与构造函数无关(`colors instanceof SpecialArray === false`)。 - **适用场景**:扩展已有对象且不能修改其构造函数时[^2]。 --- #### 7. **稳妥构造函数模式** 无 `this` 和 `new`,通过闭包访问私有数据。 **示例**: ```javascript function Person(name, age) { var o = new Object(); // 私有变量 var privateName = name; // 特权方法 o.sayName = function() { alert(privateName); }; return o; } var friend = Person("Nicholas", 29); friend.sayName(); // 只能通过此方法访问 name ``` **优点**:数据安全(无法直接访问 `privateName`)。 **适用场景**:安全环境(如防止数据被第三方脚本篡改)[^2][^3]。 --- ### 模式对比总结 | 模式 | 类型识别 | 内存效率 | 数据封装 | 适用场景 | |---------------------|----------|----------|----------|------------------------| | 工厂模式 | ❌ | ✅ | ❌ | 简单对象批量创建 | | 构造函数模式 | ✅ | ❌ | ❌ | 需类型识别但方法少 | | 原型模式 | ✅ | ✅ | ❌ | 纯共享场景(极少用) | | **组合模式** | ✅ | ✅ | ✅ | **通用默认方案** | | 动态原型模式 | ✅ | ✅ | ✅ | 组合模式的优化封装 | | 寄生构造函数模式 | ❌ | ✅ | ❌ | 扩展已有对象 | | 稳妥构造函数模式 | ❌ | ❌ | ✅ | 安全敏感环境 |
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值