首页  >  文章  >  web前端  >  JavaScript代码复用模式详解_基础知识

JavaScript代码复用模式详解_基础知识

WBOY
WBOY原创
2016-05-16 16:32:001388浏览

代码复用及其原则

<font face="NSimsun">代码复用</font>,顾名思义就是对曾经编写过的代码的一部分甚至全部重新加以利用,从而构建新的程序。在谈及代码复用的时候,我们首先可以想到的是<font face="NSimsun">继承性</font>。代码复用的原则是:

<code>优先使用对象组合,而不是类继承</code>

在js中,由于没有类的概念,因此实例的概念也就没多大意义,js中的对象是简单的键-值对,可以动态的创建和修改它们。

但在<font face="NSimsun">js</font>中,我们可以使用构造函数和<font face="NSimsun">new</font>操作符来实例化一个对象,这与其他使用类的编程语言在语法上有其相似之处。

例如:

<code>var trigkit4 = new Person();</code>

<font face="NSimsun">js</font>在调用构造函数<font face="NSimsun">Person</font>时似乎看起来是一个类,但其实际上仍然是一个函数,这让我们产生了一些假定在类的基础上的开发思路和继承模式,我们可以称之为“类式继承模式”。

传统的继承模式是需要<font face="NSimsun">class</font>关键字的,我们假定以上的类式继承模式为<font face="NSimsun">现代继承模式</font>,这是一种不需要以类的方式考虑的模式。

类式继承模式

看下面两个构造函数<font face="NSimsun">Parent()</font><font face="NSimsun">Child()</font>的例子:

<code><script type="text/javascript"><br />    function Parent(name){<br />        this.name = name || 'Allen';<br />    }<br />    Parent.prototype.say = function(){<br />        return this.name;<br />    }<br />    function Child(name){}<br />    //用Parent构造函数创建一个对象,并将该对象赋值给Child原型以实现继承<br />    function inherit(C,P){<br />        C.prototype = new P();//原型属性应该指向一个对象,而不是函数<br />    }<br />    //调用声明的继承函数<br />    inherit(Child,Parent);<br /></script></code>

当使用<font face="NSimsun">new Child()</font>语句创建一个对象时,它会通过原型从<font face="NSimsun">Parent()</font>实例获取它的功能,比如:

<code>var kid = new Child();
kid.say();
//Allen</code>

原型链

讨论一下类式继承模式下原型链的工作原理,我们将对象看做是内存中某处的块,该内存块包含数据以及指向其他块的引用。当用<font face="NSimsun">new Parent()</font>语句创建一个对象时,就会创建如下图左边的这样一个块,这个块保存了<font face="NSimsun">name</font>属性,如果想访问<font face="NSimsun">say()</font>方法,我们可以通过指向构造函数<font face="NSimsun">Parent()</font><font face="NSimsun">prototype</font>(原型)属性的隐式链接<font face="NSimsun">__proto__</font>,便可访问右边区块<font face="NSimsun">Parent.prototype</font>

那么,当使用<font face="NSimsun">var kid = new Child()</font>创建新对象时会发生什么?如下图:

使用<font face="NSimsun">new Child()</font>语句所创建的对象除了隐式链接<font face="NSimsun">__proto__</font>外,它几乎是空的。这种情况下,<font face="NSimsun">__proto__</font>指向了在<font face="NSimsun">inherit()</font>函数中使用<font face="NSimsun">new Parent()</font>语句所创建的对象

当执行<font face="NSimsun">kid.say()</font>时,由于最左下角的区块对象并没有<font face="NSimsun">say()</font>方法,因此他将通过原型链查询中间的区块对象,然而,中间的区块对象也没有<font face="NSimsun">say()</font>方法,因此他又顺着原型链查询到最右边的区块对象,而该对象正好有<font face="NSimsun">say()</font>方法。完了吗?

执行到这里的时候并没有完,在<font face="NSimsun">say()</font>方法中引用了<font face="NSimsun">this.name</font>,this指向构造函数所创建的对象,在这里,它指向了<font face="NSimsun">new Child()</font>这个区块,然而,<font face="NSimsun">new Child()</font>中并没有<font face="NSimsun">name</font>属性,为此,将查询中间区块,而中间区块正好有<font face="NSimsun">name</font>属性,至此,原型链的查询完毕。

更详细的讨论请查看我这篇文章:javascript学习笔记(五)原型和原型链详解

共享原型

本模式的法则在于:可复用的成员应该转移到原型中而不是放置在this中。因此,处于继承的目的,任何值得继承的东西都应该放在原型中实现。所以,可以将子对象的原型与父对象的原型设置为相同即可,如下示例所示:

<code>function inherit(C,P){<br>    C.prototype = P.prototype;<br>}</code>

子对象和父对象共享同一个原型,并且可以同等的访问<font face="NSimsun">say()</font>方法。然而,子对象并没有继承<font face="NSimsun">name</font>属性

原型继承

原型继承是一种“现代”无类继承模式。看如下实例:

<code><script type="text/javascript"><br />    //要继承的对象<br />    var parent = {<br />        name : "Jack"  //这里不能有分号哦<br />    };</script></code>
<code>    //新对象<br>    var child = Object(parent);</code>
<code>    alert(child.name);//Jack<br></code>

在原型模式中,并不需要使用对象字面量来创建父对象。如下代码所示,可以使用构造函数来创建父对象,这样做的话,自身的属性和构造函数的原型的属性都将被继承。

<code><script type="text/javascript"><br />    //父构造函数<br />    function Person(){<br />        this.name = "trigkit4";<br />    }<br />    //添加到原型的属性<br />    Person.prototype.getName = function(){<br />        return this.name;<br />    };<br />    //创建一个新的Person类对象<br />    var obj = new Person();<br />    //继承<br />    var kid = Object(obj);<br />    alert(kid.getName());//trigkit4<br /></script></code>

本模式中,可以选择仅继承现有构造函数的原型对象。对象继承自对象,而不论父对象是如何创建的,如下实例:

<code><script type="text/javascript"><br />    //父构造函数<br />    function Person(){<br />        this.name = "trigkit4";<br />    }<br />    //添加到原型的属性<br />    Person.prototype.getName = function(){<br />        return this.name;<br />    };<br />    //创建一个新的Person类对象<br />    var obj = new Person();<br />    //继承<br />    var kid = Object(Person.prototype);<br />    console.log(typeof kid.getName);//function,因为它在原型中<br />    console.log(typeof kid.name);//undefined,因为只有该原型是继承的<br /></script></code>

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn