javascript继承

原型链是 JavaScript 中实现继承的默认方式

JavaScript 是一种完全依靠对象的语言,其中没有类(class)的概念

当我们用某一个构造器创建对象时,其属性就会被添加到 this 中去。并且当被添加的属性实际上不会随着实体改变时,这种做法会显得很没有效率。

我们也可以选择将 name 属性添加到原型上去,这样一来所有实体就可以共享这个属性了:
function Shape() {}
Shape.prototype.name = ‘Shape’;
这样一来,当我们再用 new Shape()新建对象时,name 属性就不再是新对象的私有属性了,而是被添加进了该对象的原型中。虽然这样做通常会更有效率,但这也只是针对对象实体中的不可变属性而言的, 对象的共有方法尤其适合这种共享形式。

出于效率考虑,我们应该尽可能地将一些可重用的属性和方法添加到
原型中去。如果形成了这样一个好习惯,我们仅仅依靠原型就能完成继承关系的构建了。
由于原型中的所有代码都是可重用的,这意味着继承自 Shape.prototype 比继承自 new Shape()所创建的实体要好得多。毕竟,new Shape()方式会将 Shape 的属性设定为对象自身属性,这样的代码是不可重用的(因而要将其设置在原型中),但我们可采取以下方式对效率做一些改善:
 1.不要单独为继承关系创建新对象。
 2.尽量减少运行时方法搜索(例如 toString())。

临时构造器—new F()
如果所有 prototype 属性都指向了一个相同的对象,父对象就会受到子对象属性的影响。要解决这个问题,就必须利用某种中介来打破这种连锁关系。我们可以用一个临时构造器函数来充当中介。即我们创建一个空函数 F(),并将其原型设置为父级构造器。然后,我们既可以用 new F()来创建一些不包含父对象属性的对象,同时又可以从父对象 prototype 属性中继承一切了。
该方法也对一种意见提供了支持:将所有要共享的属性与方法添加到原型
中,然后只围绕原型构建继承关系。也就是说,这种主张不鼓励将对象的自身属性纳入继承关系,因为自身属性往往随对象的不同而差别甚大,无法重用。

在传统的面向对象语言中,通常都会提供一种用于子类访问父类(有时也叫超类)的特殊语法,因为我们在实现子类方法往往需要其父类方法的额外辅助。在这种情况下,子类通常就要去调用父类中的同名方法,以便最终完成工作。

当某些东西被创建为一个对象时,它们就被存储在内存中的某个
物理位置,相关的变量和属性就会指向这些位置。而当我们将一个新对象赋值给Wee.prototype.owns 时,就相当于告诉它:“喂,忘了那个旧对象吧,快将指针转移到现在这个新对象上来”。

当对象被拷贝时,实际上拷贝的只是该对象在内存中的位置指针。这一过程就是所谓的浅拷贝,在这种情况下,如果我们修改了拷贝对象,就等同于修改了原对象。而深拷贝则可以帮助我们避免这方面的问题。
深拷贝的实现方式与浅拷贝基本相同,也需要通过遍历对象的属性来进行拷贝操作。只是在遇到一个对象引用性的属性时,我们需要再次对其调用深拷贝函数。

使用 deepCopy()函数要注意两点。
1.在拷贝每个属性之前,建议使用 hasOwnProperty()来确认不会误拷贝不需要的继承属性。
2.由于区分 Array 对象和普通 Object 对象相当繁琐,所以 ES5 标准中实现了Array.isArray()函数。这个跨浏览器的最佳解决方案(换句话说,为仅支持ES3 的环境提供 isArray()函数)虽然看起来有点取巧,但却是有效的。

对于继承来说,主要目标就是将一些现有的功能归为己有。也就是说,我们在新建一个对象时,通常首先应该继承于现有对象,然后再为其添加额外的方法与属性。对此,我们可以通过一个函数调用来完成,并且在其中混合使用我们刚才所讨论的两种方式。
具体而言就是:
 1.使用原型继承的方式,将一个已有对象设置为新对象的原型。
 2.新建一个对象后,将另一个已有对象的所有属性拷贝过来。

所谓的多重继承,通常指的是一个子对象中有不止一个父对象的继承模式。对于这种模式,有些面向对象程序语言支持,有些则不支持。我们可以对它们进行一些甄别,自行判断在复杂的应用程序设计中多重继承是否能带来方便,或者是否有这种必要使用它,以及它是否会比原型链的方式更好。但无论如何,对于 JavaScript 这样的动态语言来说,实现多重继承是很简单的,尽管语言本身没有为此提供特殊的语法单元。
多重继承实现是极其简单的,我们只需要延续属性拷贝法的继承思路依次扩展对象即可,而对参数中所继承的对象的数量没有限制。

由于在这种继承模式中,子对象构造器可以通过 call()或 apply()方法来调用父对象的构造器,因而,它通常被称为构造器盗用法(stealing a constructor),或者构造器借用法(borrowing a constructor)

在这种继承模式中,父对象的属性是以子对象自身属性的身份来重建的。这也体现了构造器借用法的一大优势:当我们创建一个继承于数组或者其他对象类型的子对象时,将获得一个完完全全的新值(不是一个引用),对它做任何修改都不会影响其父对象。
但这种模式也是有缺点的,因为这种情况下父对象的构造器往往会被调用两次:一次发生在通过 apply()方法继承其自身属性时,而另一次则发生在通过 new 操作符继承其原型时。这样一来,父对象的自身属性事实上被继承了两次。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值