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 相关文章推荐
Extjs学习笔记之一 初识Extjs之MessageBox
Jan 07 Javascript
Javascript函数式编程语言
Oct 11 Javascript
基于Jquery制作图片文字排版预览效果附源码下载
Nov 18 Javascript
jQuery简单创建节点的方法
Sep 09 Javascript
Angularjs实现带查找筛选功能的select下拉框示例代码
Oct 04 Javascript
微信小程序 滚动到某个位置添加class效果实现代码
Apr 19 Javascript
利用pm2部署多个node.js项目的配置教程
Oct 22 Javascript
webpack之devtool详解
Feb 10 Javascript
详解js中Array的方法及技巧
Sep 12 Javascript
详解Express笔记之动态渲染HTML(新手入坑)
Dec 13 Javascript
jQuery 移除事件的方法
Jun 20 jQuery
使用vant的地域控件追加全部选项
Nov 03 Javascript
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
PHP实现图片简单上传
2006/10/09 PHP
PHP Session变量不能传送到下一页的解决方法
2009/11/27 PHP
PHP运行模式的深入理解
2013/06/03 PHP
CI框架(CodeIgniter)实现的导入、导出数据操作示例
2018/05/24 PHP
jquery png 透明解决方案(推荐)
2010/08/21 Javascript
poshytip 基于jquery的 插件 主要用于显示微博人的图像和鼠标提示等
2012/10/12 Javascript
基于jquery实现后台左侧菜单点击上下滑动显示
2013/04/11 Javascript
Js参数值中含有单引号或双引号问题的解决方法
2013/11/06 Javascript
为jquery的ajaxfileupload增加附加参数的方法
2014/03/04 Javascript
jQuery表格排序组件-tablesorter使用示例
2014/05/26 Javascript
推荐一个封装好的getElementsByClassName方法
2014/12/02 Javascript
node.js中的console.trace方法使用说明
2014/12/09 Javascript
Javascript中的方法链(Method Chaining)介绍
2015/03/15 Javascript
javascript显示系统当前时间代码
2016/12/29 Javascript
很棒的一组js图片轮播特效
2017/01/12 Javascript
浅谈jquery拼接字符串效率比较高的方法
2017/02/22 Javascript
详解js静态资源文件请求的处理
2017/08/01 Javascript
webpack使用 babel-loader 转换 ES6代码示例
2017/08/21 Javascript
Angularjs 1.3 中的$parse实例代码
2017/09/14 Javascript
Easy UI动态树点击文字实现展开关闭功能
2017/09/30 Javascript
用node开发并发布一个cli工具的方法步骤
2019/01/03 Javascript
微信小程序学习笔记之目录结构、基本配置图文详解
2019/03/28 Javascript
node.js基础知识汇总
2020/08/25 Javascript
[08:40]Navi Vs Newbee
2018/06/07 DOTA
python编写暴力破解FTP密码小工具
2014/11/19 Python
Python使用scrapy采集时伪装成HTTP/1.1的方法
2015/04/08 Python
python中for语句简单遍历数据的方法
2015/05/07 Python
Python yield与实现方法代码分析
2018/02/06 Python
使用HTML5 Canvas为图片填充颜色和纹理的教程
2016/03/21 HTML / CSS
酒店管理专业学生求职信
2013/09/27 职场文书
个人求职简历中英文自我评价
2013/12/16 职场文书
王老吉广告词
2014/03/20 职场文书
农民工工资支付承诺函
2014/03/31 职场文书
安娜卡列尼娜观后感
2015/06/11 职场文书
导游词之苏州寒山寺
2019/12/05 职场文书
MySQL实战记录之如何快速定位慢SQL
2022/03/23 MySQL