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 相关文章推荐
javascript作用域链(Scope Chain)用法实例解析
Nov 30 Javascript
JavaScript+CSS实现的可折叠二级菜单实例
Feb 29 Javascript
jQuery设置单选按钮radio选中/不可用的实例代码
Jun 24 Javascript
jQuery Ajax Post 回调函数不执行问题的解决方法
Aug 15 Javascript
JavaScript中利用Array filter() 方法压缩稀疏数组
Feb 24 Javascript
vue中多个倒计时实现代码实例
Mar 27 Javascript
layui给下拉框、按钮状态、时间赋初始值的方法
Sep 10 Javascript
js实现随机div颜色位置 类似满天星效果
Oct 24 Javascript
小程序实现录音功能
Sep 22 Javascript
javascript实现多边形碰撞检测
Oct 24 Javascript
Vue基于localStorage存储信息代码实例
Nov 16 Javascript
微信小程序实现购物车功能
Nov 18 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
打造计数器DIY三步曲(中)
2006/10/09 PHP
ThinkPHP 防止表单重复提交的方法
2011/08/08 PHP
phpmailer在服务器上不能正常发送邮件的解决办法
2014/07/08 PHP
详解php几行代码实现CSV格式文件输出
2017/07/01 PHP
自写的利用PDO对mysql数据库增删改查操作类
2018/02/19 PHP
JavaScript 图片预览效果 推荐
2009/12/22 Javascript
如何制作浮动广告 JavaScript制作浮动广告代码
2012/12/30 Javascript
js解析与序列化json数据(二)序列化探讨
2013/02/01 Javascript
javascript 上下banner替换具体实现
2013/11/14 Javascript
由浅入深讲解Javascript继承机制与simple-inheritance源码分析
2015/12/13 Javascript
JavaScript实现点击文本自动定位到下拉框选中操作
2016/06/15 Javascript
angularjs $http实现form表单提交示例
2017/06/09 Javascript
用vue的双向绑定简单实现一个todo-list的示例代码
2017/08/03 Javascript
JS实现的将html转为pdf功能【基于浏览器端插件jsPDF】
2018/02/06 Javascript
Vue开发中遇到的跨域问题及解决方法
2020/02/11 Javascript
使用TS来编写express服务器的方法步骤
2020/10/29 Javascript
pymssql ntext字段调用问题解决方法
2008/12/17 Python
Python通过PIL获取图片主要颜色并和颜色库进行对比的方法
2015/03/19 Python
举例讲解Python中metaclass元类的创建与使用
2016/06/30 Python
Python实现简易版的Web服务器(推荐)
2018/01/29 Python
对python 矩阵转置transpose的实例讲解
2018/04/17 Python
python调用百度语音识别实现大音频文件语音识别功能
2018/08/30 Python
python装饰器简介---这一篇也许就够了(推荐)
2019/04/01 Python
Win10环境python3.7安装dlib模块趟过的坑
2019/08/01 Python
使用python和pygame制作挡板弹球游戏
2019/12/03 Python
Python基于paramunittest模块实现excl参数化
2020/04/26 Python
使用CSS3创建动态菜单效果
2015/07/10 HTML / CSS
美国真皮手袋品牌:GiGi New York
2017/03/10 全球购物
皇家阿尔伯特英国官方商店:Royal Albert骨瓷
2019/03/25 全球购物
应届生高等护理求职信
2013/10/12 职场文书
职工运动会邀请函
2014/02/02 职场文书
十八大感想感言
2014/02/10 职场文书
最经典的大学生职业生涯规划范文
2014/03/05 职场文书
社区两委对照检查材料
2014/08/23 职场文书
2014年职称评定工作总结
2014/11/26 职场文书
pytorch 两个GPU同时训练的解决方案
2021/06/01 Python