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的消息提示插件 DivAlert之旅(二)
Apr 01 Javascript
鼠标滑上去后图片放大浮出效果的js代码
May 28 Javascript
Javascript Ajax异步读取RSS文档具体实现
Dec 12 Javascript
jquery的ajax异步请求接收返回json数据实例
Jun 16 Javascript
Jquery之Bind方法参数传递与接收的三种方法
Jun 24 Javascript
js 通过cookie实现刷新不变化树形菜单
Oct 30 Javascript
详解JavaScript中setSeconds()方法的使用
Jun 11 Javascript
JS平滑无缝滚动效果的实现代码
May 06 Javascript
JavaScript遍历Json串浏览器输出的结果不统一问题
Nov 03 Javascript
bootstrap table列和表头对不齐的解决方法
Jul 19 Javascript
js实现秒表计时器
Dec 16 Javascript
JavaScript中遍历的十种方法总结
Dec 15 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
使用Discuz关键词服务器实现PHP中文分词
2014/03/11 PHP
ThinkPHP3.2.3数据库设置新特性
2015/03/05 PHP
PHP获取表单数据与HTML嵌入PHP脚本的实现
2017/02/09 PHP
thinkPHP框架实现图像裁剪、缩放、加水印的方法
2017/03/14 PHP
windows环境下使用Composer安装ThinkPHP5
2018/05/18 PHP
laravel高级的Join语法详解以及使用Join多个条件
2019/10/16 PHP
javascript contains和compareDocumentPosition 方法来确定是否HTML节点间的关系
2010/02/04 Javascript
js实现的类似于asp数据字典的数据类型代码实例
2014/09/03 Javascript
JavaScript实现动态创建CSS样式规则方案
2014/09/06 Javascript
超级给力的JavaScript的React框架入门教程
2015/07/02 Javascript
js+div实现文字滚动和图片切换效果代码
2015/08/27 Javascript
JavaScript实现显示函数调用堆栈的方法
2016/04/21 Javascript
快速使用Bootstrap搭建传送带
2016/05/06 Javascript
微信小程序 wxapp内容组件 text详细介绍
2016/10/31 Javascript
详解JavaScript 中getElementsByName在IE中的注意事项
2017/02/21 Javascript
Vue.js路由vue-router使用方法详解
2017/03/20 Javascript
详解ES6 Symbol 的用途
2018/10/14 Javascript
python实现基本进制转换的方法
2015/07/11 Python
利用python如何处理百万条数据(适用java新手)
2018/06/06 Python
Python实现的建造者模式示例
2018/08/06 Python
如何修复使用 Python ORM 工具 SQLAlchemy 时的常见陷阱
2019/11/19 Python
python如何实现复制目录到指定目录
2020/02/13 Python
使用python处理题库表格并转化为word形式的实现
2020/04/14 Python
美国知名的时尚购物网站:Anthropologie
2016/12/22 全球购物
好莱坞百老汇御用王牌美妆:Koh Gen Do 江原道
2018/04/03 全球购物
YSL圣罗兰美妆官方旗舰店:购买YSL口红
2018/04/16 全球购物
大三毕业自我鉴定
2014/01/15 职场文书
服务承诺书格式
2014/05/21 职场文书
学校领导班子四风问题整改意见
2014/10/02 职场文书
学校运动会广播稿
2014/10/11 职场文书
自主招生学校推荐信范文
2015/03/26 职场文书
2015年敬老月活动总结
2015/03/27 职场文书
酒店总经理岗位职责
2015/04/01 职场文书
婚礼父母致辞
2015/07/28 职场文书
《日月潭》教学反思
2016/02/20 职场文书
公文写作指导之倡议书!
2019/07/03 职场文书