继承简单来讲就是使子类拥有父类的属性和方法,而不须要重复编写相同的代码.前端
举个例子,飞机有客运机和战斗机,这两种机型的共有属性是颜色,公有方法是起飞,可是客运机的承载的是乘客,而战斗机承载的是子弹,它还有一个功能是射击.咱们就能够建立一个父类,具备属性颜色和方法起飞,这样客运及和战斗机这两个子类就能够继承该父类,而后在父类的基础上扩展本身的属性和方法.vue
继承要靠原型来实现,咱们先来了解一下原型的概念.web
查找一个对象的属性或者方法,首先会在该对象上查找,找不到会沿着原型链向上查找,所以实现继承也就是使得一些方法和属性在该对象的原型链上,这样该对象也就具备了这些属性和方法.浏览器
原型链的继承即建立构造函数的多个实例,从而这多个实例就拥有了构造函数的属性和方法.示例代码:异步
// 片断A
function Plane(color) {
this.color = color
}
Plane.prototype.fly = function() {
console.log('flying')
}
// Fighter 构造函数
function Fighter() {
this.bullets = []
}
// 继承Plane构造函数的属性和方法
Fighter.prototype = new Plane('blue')
// 特有方法
Fighter.prototype.shoot = function() {
console.log('biu biu biu')
}
var fighter1 = new Fighter()
console.log(fighter1.color) // blue
fighter1.fly() // flying
复制代码
这样fighter1就具备了父类Plane的color属性和fly方法,并在此基础上扩展了本身的shoot方法.函数
constructor指向问题 代码片断A的写法会致使一个constructor指向的问题.工具
// 正常状况下
function A(color) {
this.color = color
}
var a = new A()
a.__proto__ = A.prototype
a.constructor = A.prototype.constructor = A
// 片断A的写法
filter.__proto__ = Filter.prototype
filter.constructor = Filter.prototype.constructor
// 因为Filter.prototype = new Plane(),咱们手动更改了Filter的prototype属性
// 因此有
Filter.prototype.constructor = Plane
filter.constructor = Plane
// 为了解决上述问题,咱们须要对片断A的代码作如下调整
Fighter.prototype. = new Plane()
Fighter.prototype.constructo = Fighter
console.log(filter.constructor) // Filter
复制代码
属性共享问题post
多个实例共享父类构造函数的属性,若是共享的属性是引用类型,会致使其中一个示例最这些属性作了更改影响到其余实例中对该属性的使用.属性共享会致使数据污染,代码的可维护性下降.优化
如代码片断A这样,Fighter构造函数建立的实例的继承得来的color属性都是blue,实例的颜色最好统一是blue,否则后面一个个修改color,代码的复用性的下降了.this
// 片断B
function Plane(color) {
this.color = color
}
Plane.prototype.fly = function() {
console.log('flying')
}
function Fighter(color, content) {
Plane.call(this, color)
this.content = content
}
Fighter.prototype.shoot = function() {
console.log('biu biu biu')
}
var flighter1 = new Fighter('blue', 'zidan');
console.log(flighter1.color); // blue
console.log(flighter1.content); // zidan
flighter1.shoot(); // 'biu biu biu';
flighter1.fly(); // Uncaught TypeError: flighter1.fly is not a function
at <anonymous>:19:15
复制代码
构造函数继承的不足就片断B中既能够看出,它只能实现继承构造函数自己的属性和方法,而不能继承构造函数原型上的属性和方法.
组合继承, 顾名思义是原型链继承和构造函数函数继承的组合.父类的属性经过构造函数继承为私有属性,父类的方法经过原型链继承,弥补了原型链继承和构造函数继承的不足
function Plane(color) {
this.color = color
}
Plane.prototype.fly = function() {
console.log('flying')
}
function Fighter(color) {
Plane.call(this, color)
this.bulltes = []
}
Fighter.prototype = new Plane()
Fighter.prototype.constructor = Fighter
Fighter.prototype.shoot = function() {
console.log('biu biu biu')
}
复制代码
组合继承的方法致使了咱们重复调用了构造函数Plane.且Plane构造函数内部的color不会被用到,致使了属性冗余.
// 片断C
function Plane(color) {
this.color = color
this.pilots = []
}
Plane.prototype.fly = function() {
console.log('flying')
}
// Fighter 构造函数
function Fighter(color) {
Plane.call(this, color)
this.bullets = []
}
// 继承Plane构造函数的属性和方法
inheritPrototype(Fighter, Plane)
// 特有方法
Fighter.prototype.shoot = function() {
console.log('biu biu biu')
}
var fighter1 = new Fighter()
console.log(fighter1)
// inheritPrototype的第一种实现方式
function inheritPrototype(child, parent) {
var proto = Object.create(parent.prototype)
proto.constructor = child
child.prototype = proto
}
// inheritPrototype的第二种实现方式
function inheritPrototype(child, parent) {
var proto = Object.create(parent.prototype)
child.prototype = proto
child.prototype.constructor = child
}
// inheritPrototype的第三种实现方式
function inheritPrototype(child, parent) {
var proto = function() {}
proto.prototype = parent.prototype
child.prototype = new proto()
child.prototype.constructor = child
}
复制代码
咱们都知道,目前的js的继承的实现比较繁琐, 要调用构造函数,又要本身封装继承原型的函数,因此ES6标准将class声明类和继承类的方式归入标准,示例代码以下:
// 片断D
class Plane1 {
constructor(color) {
this.color = color
}
fly() {
console.log('flying')
}
}
// 使用extends关键字实现继承
class Fighter1 extends Plane1 {
constructor(color, content) {
super(color)
this.content = content
}
shoot() {
console.log('biu biu biu')
}
}
const fight1 = new Fighter1('blue', 'zidan')
fight1.color // blue
fight1.content // zidan
fight1.fly() // flying
fight1.shoot() // biu biu biu
复制代码
注意: 目前部分现代浏览器新版本已经实现对 ES6 中的class和继承的,可是注意在旧版本或者 IE 浏览器中是不支持的,因此使用的时候要注意,或者配合使用 Babel 等编译工具。
啦啦啦~~~,写完了,后续我会坚持一系列的前端知识的分享的,但愿大家读完个人文章后可以有所收获~~~.听明白和讲明白之间仍是差了不少,若是我有表达不当的地方或者能够优化的地方还请指出,但愿努力的咱们都能成为优秀的本身~~~