JavaScript代码复用模式实例分析


Posted in Javascript onDecember 02, 2012

任何编程都提出代码复用,否则话每次开发一个新程序或者写一个新功能都要全新编写的话,那就歇菜了,但是代码复用也是有好要坏,接下来的两篇文章我们将针对代码复用来进行讨论,第一篇文避免篇,指的是要尽量避免使用这些模式,因为或多或少有带来一些问题;第二排是推荐篇,指的是推荐大家使用的模式,一般不会有什么问题。

模式1:默认模式
代码复用大家常用的默认模式,往往是有问题的,该模式使用Parent()的构造函数创建一个对象,并且将该对象赋值给Child()的原型。我们看一下代码:

function inherit(C, P) { C.prototype = new P();} 
// 父构造函数function Parent(name) { this.name = name || 'Adam';} 
// 给原型添加say功能Parent.prototype.say = function () { return this.name;}; 
// Child构造函数为空function Child(name) {} 
// 执行继承inherit(Child, Parent);var kid = new Child();console.log(kid.say()); 
// "Adam"var kiddo = new Child();kiddo.name = "Patrick";console.log(kiddo.say()); 
// "Patrick"// 缺点:不能让参数传进给Child构造函数var s = new Child('Seth');console.log(s.say()); 
// "Adam"这种模式的缺点是Child不能传进参数,基本上也就废了。

模式2:借用构造函数
该模式是Child借用Parent的构造函数进行apply,然后将child的this和参数传递给apply方法:

// 父构造函数function Parent(name) { this.name = name || 'Adam';} 
// 给原型添加say功能Parent.prototype.say = function () { return this.name;}; 
// Child构造函数function Child(name) { Parent.apply(this, arguments);}var kid = new Child("Patrick");console.log(kid.name); 
// "Patrick"// 缺点:没有从构造函数上继承say方法console.log(typeof kid.say); 
// "undefined"缺点也很明显,say方法不可用,因为没有继承过来。

模式3:借用构造函数并设置原型
上述两个模式都有自己的缺点,那如何把两者的缺点去除呢,我们来尝试一下:
// 父构造函数function Parent(name) { this.name = name || 'Adam';}// 给原型添加say功能Parent.prototype.say = function () { return this.name;};// Child构造函数function Child(name) { Parent.apply(this, arguments);}Child.prototype = new Parent();var kid = new Child("Patrick");console.log(kid.name); // "Patrick"console.log(typeof kid.say); // functionconsole.log(kid.say()); // Patrickconsole.dir(kid);delete kid.name;console.log(kid.say()); // "Adam"运行起来,一切正常,但是有没有发现,Parent构造函数执行了两次,所以说,虽然程序可用,但是效率很低。

模式4:共享原型
共享原型是指Child和Parent使用同样的原型,代码如下:

function inherit(C, P) { C.prototype = P.prototype;} 
// 父构造函数function Parent(name) { this.name = name || 'Adam';} 
// 给原型添加say功能Parent.prototype.say = function () { return this.name;}; 
// Child构造函数function Child(name) {}inherit(Child, Parent);var kid = new Child('Patrick');console.log(kid.name); 
// undefinedconsole.log(typeof kid.say); 
// functionkid.name = 'Patrick';console.log(kid.say()); 
// Patrickconsole.dir(kid);确定还是一样,Child的参数没有正确接收到。

模式5:临时构造函数
首先借用构造函数,然后将Child的原型设置为该借用构造函数的实例,最后恢复Child原型的构造函数。代码如下:

/* 闭包 */var inherit = (function () { var F = function () { }; return function (C, P) { F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; CC.prototype.constructor = C; }} ());function Parent(name) { this.name = name || 'Adam';}// 给原型添加say功能Parent.prototype.say = function () { return this.name;};// Child构造函数function Child(name) {}inherit(Child, Parent);var kid = new Child();console.log(kid.name); // undefinedconsole.log(typeof kid.say); // functionkid.name = 'Patrick';console.log(kid.say()); // Patrickvar kid2 = new Child("Tom");console.log(kid.say()); console.log(kid.constructor.name); // Childconsole.log(kid.constructor === Parent); // false问题照旧,Child不能正常接收参数。 模式6:klass 
这个模式,先上代码吧: 
var klass = function (Parent, props) { var Child, F, i; // 
1. // 新构造函数 Child = function () { if (Child.uber && Child.uber.hasOwnProperty("__construct")) { Child.uber.__construct.apply(this, arguments); } if (Child.prototype.hasOwnProperty("__construct")) { Child.prototype.__construct.apply(this, arguments); } }; // 
2. // 继承 ParentParent = Parent || Object; F = function () { }; F.prototype = Parent.prototype; Child.prototype = new F(); Child.uber = Parent.prototype; ChildChild.prototype.constructor = Child; / 
3. // 添加实现方法 for (i in props) { if (props.hasOwnProperty(i)) { Child.prototype[i] = props[i]; } } 
// return the "class" return Child;};var Man = klass(null, { __construct: function (what) { console.log("Man's constructor"); this.name = what; }, getName: function () { return this.name; }});var first = new Man('Adam'); 
// logs "Man's constructor"first.getName(); 
// "Adam"var SuperMan = klass(Man, { __construct: function (what) { console.log("SuperMan's constructor"); }, getName: function () { var name = SuperMan.uber.getName.call(this); return "I am " + name; }});var clark = new SuperMan('Clark Kent');clark.getName(); 
// "I am Clark Kent"console.log(clark instanceof Man); 
// trueconsole.log(clark instanceof SuperMan);

看着是不是有点晕,说好点,该模式的语法和规范拧得和别的语言一样,你愿意用么?

总结
以上六个模式虽然在某种特殊情况下实现了某些功能,但是都存在各自的缺点,所以一般情况,大家要避免使用。

Javascript 相关文章推荐
Jquery 一次处理多个ajax请求的代码
Sep 02 Javascript
onbeforeunload与onunload事件异同点总结
Jun 24 Javascript
js数组转json并在后台对其解析具体实现
Nov 20 Javascript
Javascript连接Access数据库完整实例
Aug 03 Javascript
轻松学习jQuery插件EasyUI EasyUI实现树形网络基本操作(2)
Nov 30 Javascript
easyui window refresh 刷新两次的解决方法(推荐)
May 18 Javascript
Javascript实现从小到大的数组转换成二叉搜索树
Jun 13 Javascript
vue 详情跳转至列表页实现列表页缓存
Mar 27 Javascript
Vue2.0使用嵌套路由实现页面内容切换/公用一级菜单控制页面内容切换(推荐)
May 08 Javascript
微信小程序实现搜索功能
Mar 10 Javascript
jQuery实现放大镜案例
Oct 19 jQuery
vue使用vue-quill-editor富文本编辑器且将图片上传到服务器的功能
Jan 13 Vue.js
JSONP 跨域访问代理API-yahooapis实现代码
Dec 02 #Javascript
script标签属性type与language使用选择
Dec 02 #Javascript
JavaScript中valueOf函数与toString方法深入理解
Dec 02 #Javascript
json对象转字符串如何实现
Dec 02 #Javascript
javascript 构造函数强制调用经验总结
Dec 02 #Javascript
js精度溢出解决方案
Dec 02 #Javascript
JavaScript词法作用域与调用对象深入理解
Nov 29 #Javascript
You might like
全国FM电台频率大全 - 22 重庆市
2020/03/11 无线电
一首老MP3,致敬WAR3经典
2021/03/08 魔兽争霸
smarty模板引擎中变量及变量修饰器用法实例
2015/01/22 PHP
PHP实现验证码校验功能
2017/11/16 PHP
php 使用mpdf实现指定字段配置字体样式的方法
2019/07/29 PHP
javascript Prototype 对象扩展
2009/05/15 Javascript
Javascript 中介者模式实例
2009/12/16 Javascript
jquery实现table鼠标经过变色代码
2013/09/25 Javascript
jQuery探测位置的提示弹窗(toolTip box)详细解析
2013/11/14 Javascript
javascript实现获取浏览器版本、操作系统类型
2015/01/29 Javascript
JQuery select(下拉框)操作方法汇总
2015/04/15 Javascript
node.js调用C++开发的模块实例
2015/07/03 Javascript
基于jQuery实现Ajax验证用户名是否存在实例
2016/03/30 Javascript
JQuery解析XML的方法小结
2016/04/02 Javascript
详解Sea.js中Module.exports和exports的区别
2017/02/12 Javascript
Java中int与integer的区别(基本数据类型与引用数据类型)
2017/02/19 Javascript
在 Angular 中使用Chart.js 和 ng2-charts的示例代码
2017/08/17 Javascript
webpack打包并将文件加载到指定的位置方法
2018/02/22 Javascript
JavaScript监听触摸事件代码实例
2019/12/30 Javascript
[59:36]2018DOTA2亚洲邀请赛 4.3 突围赛 Secret vs VG 第二场
2018/04/04 DOTA
解决出现Incorrect integer value: '' for column 'id' at row 1的问题
2017/10/29 Python
Python3.5模块的定义、导入、优化操作图文详解
2019/04/27 Python
如何基于Python实现自动扫雷
2020/01/06 Python
Python matplotlib实时画图案例
2020/04/23 Python
香港草莓网:Strawberrynet香港
2019/05/10 全球购物
新西兰第一的行李箱网站:luggage.co.nz
2019/07/22 全球购物
意大利和国际奢侈品牌购物网站:Suitnegozi.com
2021/01/15 全球购物
Can a struct inherit from another struct? (结构体能继承结构体吗)
2016/09/25 面试题
厨房领班竞聘演讲稿
2014/04/23 职场文书
2014乡镇班子个人对照检查材料思想汇报
2014/09/26 职场文书
教师年终个人总结
2015/02/11 职场文书
党员承诺书格式范文
2015/04/28 职场文书
欢送领导祝酒词
2015/08/12 职场文书
争做文明公民倡议书
2019/06/24 职场文书
七年级作文之秋游
2019/10/21 职场文书
Python基础知识之变量的详解
2021/04/14 Python