初涉JavaScript模式 (7) : 原型模式 【三】
组合使用构造函数模式和原型模式
上篇,我们提到了原型模式的缺点,就是每个实例不能拥有自己的属性,因为纯原型模式所有的属性都是公开给每个实例的,故我们可以组合使用构造函数模式和原型模式。构造函数用来定义实例的属性,而原型模式用来定义方法和公用属性。这样的话,每个实例都有自己的属性副本(而不是指向原型的引用),同时它也共享原型上方法的引用。而且,这种混合模式还支持对构造函数传参,所以可以说是结合了两种模式的优点。示例如下:
```javascript
function Animal(name,type){
this.name = name;
this.type = type;
}
Animal.prototype = {
constructor: Animal,
sayName : function(){
console.log("oh ~~~~我的名字叫"+this.name);
}
};
var tom = new Animal("tom","Cat");
var jerry = new Animal("jerry","Mouse");
console.log(tom.name === jerry.name); //false
console.log(tom.sayName === jerry.sayName); //true
```
上面的例子中,实例属性都都是在构造函数中定义的,故每个实例的属性都是私有的副本,不会互相影响。而在原型中定义的方法,每个实例的引用都是指向同一个方法(原型上的)。这种组合模式是在JS中使用最广的一种创建自定义类型的方法,推荐使用。
动态原型模式
动态原型模式是用来解决原型和构造函数独立的问题。很多情况下,构造函数和原型都是相互独立的,这有的时候不太美观,而为了解决这么一批对代码有洁癖的程序猿(例如我),在JS中衍生了一种奇葩的解决方案。这种方案就是动态原型模式,他把所有的信息都封装在构造函数中,而通过在构造函数中初始化原型(仅在必要情况下),这样就不仅保留了构造函数模式和原型模式的优点,而且单独的相对独立也得到了解决。
而仅在必要情况下初始化原型,可以通过检查某个应该存在的方法是否有效来判断。代码如下:
```javascript
function Animal(name,type){
this.name = name;
this.type = type;
if(typeof this.sayName != "function"){
Animal.prototype.sayName = function(){
console.log("oh~~~my name is "+this.name);
}
}
}
var tom = new Animal("tom","Cat");
var jerry = new Animal("jerry","Mouse");
console.log(tom.name === jerry.name); //false
console.log(tom.sayName === jerry.sayName); //true
```
以上代码会检查原型是否初始化完成,如果没有就对原型进行初始化。要注意的是使用动态原型模式时,不能以字面量的形式重写原型对象,因为这样就切断了已有实例和新原型的关系。不过虽然这种方法很好用,但是我觉得这种方式(以if判断)容易造成代码的混淆,而且把原型init放在构造函数中也不是一个很好的方法,所以最后我还是选择了独立原型和构造函数,只不过我对原型和构造函数上面再做了一层封装。(个人喜好,要喷请轻点。。。)
总结
通过这三篇(这一篇算是收尾),对原型模式做了大体的归纳,由于经验和阅历的关系,没有办法面面俱到。文章内容参考了高程,设计模式,编程模式等,在写的过程中,也对自己的知识体系进行了一遍梳理,收获很大。
后记
如果你在文中发现有什么错误或则疑惑,我们可以共同讨论。群 239147101(N多JS大神)。
最新文章
- MS SQL错误:SQL Server failed with error code 0xc0000000 to spawn a thread to process a new login or connection. Check the SQL Server error log and the Windows event logs for information about possible related problems
- Oracle的多表查询
- poj 2377 Bad Cowtractors
- Cygwin,Mingw
- The server quit without updating PID file (mysql.pid)一次意外mysql停止运行备忘录
- QTableWidget查找指定项(由github处学习到)
- Python 3 学习笔记
- mouseover和this的巧用
- tp 框架的增
- AVAudioFoundation(2):音视频播放
- jq-toggle
- 了解前端中的SPA
- windows控件理论学习
- 信息摘要算法之一:MD5算法解析及实现
- octave基本指令4
- HTML <;meta>; 标签 和 http-equiv
- C++面向对象高级开发课程(第二周)
- HDU 4240
- python中的模块及包及软件目录结构规范
- Swift中的闭包(Closure)[转]
热门文章
- 加密解密,CryptoStream()的使用
- Android 子线程请求ASP.NET后台
- 动态规划——B 最大高度问题
- [Locked] Shortest Word Distance I &; II &; III
- LA 3263 欧拉定理
- kickstrt脚本for cobbler基于system-config-kickstart配置
- SunTlsRsaPremasterSecret KeyGenerator not available问题解决
- 3Dmax导出fbx文件缺失纹理问题
- 如何看懂Code128条形码
- android图片缓存框架Android-Universal-Image-Loader(二)