JavaScript代码复用模式实例分析

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

模式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);

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

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

(0)

相关推荐

  • 简单谈谈javascript代码复用模式

    代码复用有一个著名的原则,是GoF提出的:优先使用对象组合,而不是类继承.在javascript中,并没有类的概念,所以代码的复用,也并不局限于类式继承.javascript中创建对象的方法很多,有构造函数,可以使用new创建对象,并且可以动态的修改对象.javascript的非类式继承(可称为现代继承模式)复用方法也很多,例如,利用其它对象组合成所需要的对象,对象混入技术,借用和复用所需要的方法. 类式继承模式-默认模式 两个构造函数Parent和Child的例子: 复制代码 代码如下: fu

  • JavaScript代码复用模式详解

    代码复用及其原则 代码复用,顾名思义就是对曾经编写过的代码的一部分甚至全部重新加以利用,从而构建新的程序.在谈及代码复用的时候,我们首先可以想到的是继承性.代码复用的原则是: 优先使用对象组合,而不是类继承 在js中,由于没有类的概念,因此实例的概念也就没多大意义,js中的对象是简单的键-值对,可以动态的创建和修改它们. 但在js中,我们可以使用构造函数和new操作符来实例化一个对象,这与其他使用类的编程语言在语法上有其相似之处. 例如: var trigkit4 = new Person();

  • JavaScript代码复用模式实例分析

    任何编程都提出代码复用,否则话每次开发一个新程序或者写一个新功能都要全新编写的话,那就歇菜了,但是代码复用也是有好要坏,接下来的两篇文章我们将针对代码复用来进行讨论,第一篇文避免篇,指的是要尽量避免使用这些模式,因为或多或少有带来一些问题:第二排是推荐篇,指的是推荐大家使用的模式,一般不会有什么问题. 模式1:默认模式 代码复用大家常用的默认模式,往往是有问题的,该模式使用Parent()的构造函数创建一个对象,并且将该对象赋值给Child()的原型.我们看一下代码: 复制代码 代码如下: fu

  • JavaScript实现Iterator模式实例分析

    本文实例讲述了JavaScript实现Iterator模式的方法.分享给大家供大家参考.具体分析如下: 经常在网上看到有不少JS设计模式的示例.这里写一下JavaScript实现Iterator模式的方法,记录在此,仅作备忘: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quo

  • 深入理解JavaScript系列(46):代码复用模式(推荐篇)详解

    介绍 本文介绍的四种代码复用模式都是最佳实践,推荐大家在编程的过程中使用. 模式1:原型继承 原型继承是让父对象作为子对象的原型,从而达到继承的目的: 复制代码 代码如下: function object(o) {     function F() {     } F.prototype = o;     return new F(); } // 要继承的父对象 var parent = {     name: "Papa" }; // 新对象 var child = object(p

  • Java设计模式之静态代理模式实例分析

    本文实例讲述了Java设计模式之静态代理模式.分享给大家供大家参考,具体如下: 代理模式,可以通过代理可以在原来的基础上附加一些其他的操作.静态代理模式相对比较简单无需再程序运行时动态的进行代理. 静态代理模式的角色: ① 抽象角色:真实对象和代理对象的共同接口.其中声明真实对象和代理对象需要做的事. ② 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用. ③ 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作. 下面提

  • 深入理解JavaScript系列(45):代码复用模式(避免篇)详解

    介绍 任何编程都提出代码复用,否则话每次开发一个新程序或者写一个新功能都要全新编写的话,那就歇菜了,但是代码复用也是有好要坏,接下来的两篇文章我们将针对代码复用来进行讨论,第一篇文避免篇,指的是要尽量避免使用这些模式,因为或多或少有带来一些问题:第二排是推荐篇,指的是推荐大家使用的模式,一般不会有什么问题. 模式1:默认模式 代码复用大家常用的默认模式,往往是有问题的,该模式使用Parent()的构造函数创建一个对象,并且将该对象赋值给Child()的原型.我们看一下代码: 复制代码 代码如下:

  • JavaScript变量提升和严格模式实例分析

    本文实例讲述了JavaScript变量提升和严格模式.分享给大家供大家参考,具体如下: 1.什么是变量提升 所谓的变量提升指的是:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体(作用域)的最顶部. 下面我们通过一个例子来详细说明一下. //变量声明在使用之前 var x; console.log(x);//undefined //变量声明在使用之后 console.log(y);//undefined var y; //上面的式子可以写成下面的样子 /* 变量提升:把x,y提

  • JavaScript创建对象的四种常用模式实例分析

    本文实例讲述了JavaScript创建对象的四种常用模式.分享给大家供大家参考,具体如下: 这里介绍了javascript中创建对象常用的几种模式,包括:工厂模式,构造函数模式,原型模式,组合构造函数与原型的模式,动态原型模式. 一.工厂模式 看如下代码: function getMySon(name,sex){ var o={}; o.name=name; o.sex=sex; o.sayName = function(){ alert(this.name); } return o; } so

  • 《javascript设计模式》学习笔记五:Javascript面向对象程序设计工厂模式实例分析

    本文实例讲述了Javascript面向对象程序设计工厂模式.分享给大家供大家参考,具体如下: 工厂模式和单例模式(https://www.jb51.net/article/184230.htm)应该是设计模式中应用最多的模式了,工厂模式的定义:提供创建对象的接口(来自百度百科:http://baike.baidu.com/view/1306799.htm),意思就是根据领导(调用者)的指示(参数),生产相应的产品(对象). 1.简单工厂模式 简单工厂也就是按照上面的定义,根据不同的参数返回不同的

随机推荐