组合使用构造函数模式和原型模式

上篇,我们提到了原型模式的缺点,就是每个实例不能拥有自己的属性,因为纯原型模式所有的属性都是公开给每个实例的,故我们可以组合使用构造函数模式和原型模式。构造函数用来定义实例的属性,而原型模式用来定义方法和公用属性。这样的话,每个实例都有自己的属性副本(而不是指向原型的引用),同时它也共享原型上方法的引用。而且,这种混合模式还支持对构造函数传参,所以可以说是结合了两种模式的优点。示例如下:

```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大神)。

最新文章

  1. 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
  2. Oracle的多表查询
  3. poj 2377 Bad Cowtractors
  4. Cygwin,Mingw
  5. The server quit without updating PID file (mysql.pid)一次意外mysql停止运行备忘录
  6. QTableWidget查找指定项(由github处学习到)
  7. Python 3 学习笔记
  8. mouseover和this的巧用
  9. tp 框架的增
  10. AVAudioFoundation(2):音视频播放
  11. jq-toggle
  12. 了解前端中的SPA
  13. windows控件理论学习
  14. 信息摘要算法之一:MD5算法解析及实现
  15. octave基本指令4
  16. HTML <meta> 标签 和 http-equiv
  17. C++面向对象高级开发课程(第二周)
  18. HDU 4240
  19. python中的模块及包及软件目录结构规范
  20. Swift中的闭包(Closure)[转]

热门文章

  1. 加密解密,CryptoStream()的使用
  2. Android 子线程请求ASP.NET后台
  3. 动态规划——B 最大高度问题
  4. [Locked] Shortest Word Distance I & II & III
  5. LA 3263 欧拉定理
  6. kickstrt脚本for cobbler基于system-config-kickstart配置
  7. SunTlsRsaPremasterSecret KeyGenerator not available问题解决
  8. 3Dmax导出fbx文件缺失纹理问题
  9. 如何看懂Code128条形码
  10. android图片缓存框架Android-Universal-Image-Loader(二)