详解Ext.extend 函数

来源:互联网 发布:c语言求素数代码 编辑:程序博客网 时间:2024/05/17 02:21
  •   

      这段代码是Ext核心包中的关于继承的方法,其作用是利用JS中的原形继承来实现Ext中的JS类继承。由于JS中的原形继承和传统的面向对象程序的类继承有较大差别我们这里需要梳理JS中的关于比较核心的知识点:

  • js中怎样写一个类?

       js中的并没有用专门的关键字来作为描述类的符号,尽管"class"在javascript中是作为保留字,但在javascript中描述一个类并不是用"class"而是用"function".下面我们就来写一个例子类.

       这就是一个描述"人"的类,它只有一个属性就是"name".虽然它通常是被认是是函数,但事实上在javascript中我们要写一个类时,就是这样写的。同时在下面我们还通过这个类new 了一个它的对象"p".这看起来跟JAVA 或 c++都有点相似。然后我们打印出了p的name属性,从这相结果中,我们可以看出作为构造类的函数,实际上比较类似于面象对象中的构造函数。也就是说我们在调用new Person('andy')的时候执行的就是那段函数.这个对象现在还没任何动作,我们来给它增加一个动作:

 

这样就给Person类增加了一个叫"eat"的动作,但是记住我们给类增加一个方法不能这么加:

 

 

 

这样是错误的,第一种增加动作的方法是正确的是因为,在构造函数里有这么一句this.eat = function(){....} ,这是一种显示的给类加动作的方法,而第二种增加动作的方法之所以不正确,这是由JS的原形继承的机制决定的。什么叫“原形”下面我们就来引入这一概念:

  • 关于"prototype"

      prototype即是我们说的“原形",javascript中的每一个类都有一个prototype,prototype是一个JS对象。它的作用相当于是一个模板,所有类的对象,都关复制了这个模板,所以只要是模板中含有的属性,所有的对象都具有,只要是模板具有的动作,所有的对象也都具有。

 

 

从上面,可以看出prototype确实相当于一个模板,所有类的对象都复制了这个模板,然而我们也看出并不是类的所有属性都在prototype中,比如说先前我们加入的name属性和eat方法,这也可见往一个类中增加属性和方法有两种方法一种是在构造函数中加入,另一种则是在prototype这个模板对象中加入.

 

在Body中有prototype这个属性,p 在构造的时候复制了这个属性,但如果用alert(p.prototype);语句我们打印出来的却是"undefined",为什么呢,因为在javascript中prototype是隐藏在每个对象中的,作为一个内部原形.

 

 

  • 关于constructor

      上面我们详解了prototype ,但是prototype内部有一个比较特殊的方法,它就是constructor,先看下面的代码:

 

 

 

 

 

 

 

运行上面代码,我们看到这个所谓的constructor函数就是Person类的构造函数,而且在对象p中也有一个这样的constructor方法,其实也好解释,为什么呢?我们之前说过了,每个对象会复制一份prototype的模板,prototype中有的方法和属性也就成了对象自己的方法和属性了,既然Prototype中有constructor这样一个方法,那自然每个对象中也有这样一个方法了.

    这里就有了一个问题,原形中的constructor既然默认就是类的构造函数,那么我们能不能改变这个默认的方法,答案是肯定的,我们可以将它替换成另一个我们自己定义的方法,这样每个对象的constructor方法也成了我们自定义的方法,但如果替换了之后,我们在new 一个对象时执行的是哪个方法呢?可以通过代码验证:

 

 

可以看到虽然我们替换了prototype的constructor但是在new 一个对象的时候,仍然执行的是我们定义一个类时的函数。也就是Person函数本身.

 

 

 


上面是关于javascript中原形继承知识的一些讲解,如果明白了这些底层的知识,那么读懂Ext.extend方法就并不难了,我只讲讲这个方法做了哪些事:

1.将子类的prototype复制为跟超类一模一样,但是请注意我这里说提复制,并没有把超类的prototype直接赋给子类的prototype,而且代码里也作的很精巧,这里可能有一点难看懂。同时,把子类原形的constructor指向子类构造函数本身.

 

2.检查超类的constructor是不是等于Object.prototype.constructor,如果是,则将它指向为超类本身的构造函数.

 

3.在子类的prototype中 加入了override方法,这样就在每个子类的对象中都可以用这个方法.

 

4.给子类本身加入了override和extend方法,记住这里是给类本身,而不是在prototype中增加的方法,所以在子类的对象中是不能调用的。

 

5.将参数override中的发生,复制到子类的prototype中去,关于这一点,需要大家认真的看Ext.override这个方法的原码.

 

 

 

 

 

原创粉丝点击