中国疾病
网站地图
RSS订阅
匿名投稿
您的位置:网站首页 > 草本类

来聊聊JavaScript核心之伪类子类

作者:habao 来源:未知 日期:2018-7-18 23:21:35 人气: 标签:伪类怎么用
导读:一个类可以工作的很好,当你想制造一批相似的对象。但是假如你想要第二类对象它只是和Car类依稀类似会怎么样?还看这个列子假如你需要创建一辆警车,它有一个呼叫…

  一个类可以工作的很好,当你想制造一批相似的对象。但是假如你想要第二类对象它只是和Car类依稀类似会怎么样?还看这个列子

  假如你需要创建一辆警车,它有一个呼叫功能call();我们不会把这个方法写进函数类里,因为非警车的普通汽车不会拥有这个方法,那我们实现这个相同类的幼稚的一个方法就是从Car类中拷贝所有代码到第二个类中,然后重构这个类

  我们为这两个类取不同的名字以区别他们。这里的grab方法是仅有敌人车才会用到的方法。而call方法仅仅对警车是有用的。看一下内存中的情况

  这种场景下,我们有两个不同的构造函数,都可以生产出基本相同的对象,但是都有各自的新方法grab或者call.这种方法可以解决问题,但是存在大量重复代码,需要优化。

  假设我们在这之前构造一个函数做大部分的工作,之后让Van和Cop类做剩下少量的定制,使得他们区别与普通汽车,我们把这个新的函数成为父类。重构后代码如下

  当然,我们使用函数类来创建子类很容易。那么现在可以想一下如果用伪类模式应该怎么做。应该怎样写伪类模式的子类呢?我们从头开始分析,用一个新的例子

  还是Van是Car的子类,zed是Car的实例对象,amy是Van的实例对象。到此,父类Car我们已经编写完毕,下面继续编写子类。我们先为子类写一个构造函数,内存里应该构建了一个新的子类,并且这个子类应该从父类中继承很多属性

  但是这样做的话没什么意义,一旦Car有什么修改,Van也得跟着修改。所以这样不好。或者我们也可以在Van中调用Car函数,即这样

  但是这样仍然有问题,首先在内存里,它将产生一个新的实例对象(但不会作为该函数返回值),而代码 Var amy = new Van(9);将会创建新的对象作为调用new Van()的结果。

  其中比较特殊的是,它将会设置关键字this等于一个全新创建的对象。正是我们因为使用了new创建Van(),它将创建另一个新的对象,但是并不意味着这个Car函数会运行这个新对象作为this的值。事实上两个不同的object.create语句被插入到两个不同的函数里,会有两次使用关键字new的结果。如果这么写,不管你的Van有没有用new关键字来创建实例,在内存里都会创建一个全新的委托到Car类上的对象。如果你用new关键字调用Van,那么你已经创建了一个新对象,并且你并不需要另一个对象。或许有人会想直接将这个使用Car构造器构造的对象赋值给关键字this,比如这样

  但是在代码给关键字this赋值是不允许的,即使解释器允许做这样的事情。因此它仍旧解决不了创建了两个不同对象的问题。那么或许也可以去掉关键字new,直接调用Car函数呢

  这样做看似行,那么仔细想想Car函数中的this会指向什么呢?答案是Car函数将会在全局作用域的执行中去运行,this指向global。因为这个Car函数被作为一个函数调用。如果这样写调用var amy = new Van(9);实际上将会绑定一个指向数字9的全局变量loc

  那么如果我们调用Car函数,我们只需要确定它运行在正确的执行中,我们有方法可以指定函数被调用时的执行,.call方法允许我们在调用函数时指定一个特定的执行。这意味着Car函数里参数this表现得更像一个传入函数的参数。这样写

  是可以成功输出9的。但是此时amy.move()并不能运行,当执行到这一句时,代码会终止。因为amy对象没有move方法,根据原型链原理,它会在它的构造函数的原型上去查找,即Van.prototype,但是Van.prototype里面也没有,Van.prototype的原型是Object.prototype,但是也没有move方法。

  到此,我们已经实现让子类的特定代码调用父类的特定代码,但由于事实上我们使用原型链实现继承的效果,我们需要将子类原型链到父类原型,是父类中相似的代码能被继承。amy确实委托到Van.prototype,但是它和Car.prototype并没有一毛钱的关系,因此我们需要将Van.prototype委托到Car.prototype。理情况下,我们可以修改Van.prototype,以便它能直接委托到Car.prototype

  内存中情况是这样,我们希望他这样工作,Van.prototype对象一直向上委托到Car.prototype。这样它就会和Car实例变得很类似,因为它们都能把字段查询委托给Car的prototype属性。

  但是版本的语言里这种写法是不允许的,取而代之我们将不得不用我们的新创建的对象重写这个原型对象。

  但是注意当你把一个变量或者属性赋值给另一个时JavaScript不会做任何拷贝操作,因为它们是同一个对象。

  如果是这样的话,加在Car原型上的方法,一定在Van原型中存在,反之亦然。因此如果我们加了一个Van.prototype。grab方法,那么会使Car.prototype也拥有一个.grab方法,简而言之,我们不希望Van.prototype和Car.prototype是同一个对象,所以我们还有找一种替代方法来替代Van.prototype和Car.prototype相等。

  现在如果我们需要amy有一个新的方法grab,那么我们之间将次方法添加到构造函数的的原型对象上就行了

  到此,我们似乎完成了整个功能,但是本属于Van.prototype的一个属性丢失了,就是structor。

  到此,如果你从我的前几篇文章一读来,那么你关于不同代码的复用模式已经了解很多,包括函数模式、修饰器模式和JavaScript原生提供的所有主要的类模式以及它们相应的子类技术。

  本文由 790游戏(www.790.kim)整理发布

本文网址:
下一篇:没有资料
共有:条评论信息评论信息
发表评论
姓 名:
验证码: