继承,使子类具有父类的方法和属性
在ES5继承的实现非常有趣的,由于没有传统面向对象类的概念,Javascript利用原型链的特性来实现继承。
原型链的特点和实现已经在之前的一篇整理说过了,就是通过将子类构造函数的原型作为父类构造函数的实例,这样就连通了子类-子类原型-父类,原型链的特点就是逐层查找,从子类开始一直往上直到所有对象的原型Object.prototype,找到属性方法之后就会停止查找,所以下层的属性方法会覆盖上层。
一个基本的基于**原型链的继承**过程大概是这样的:
~~~
//父类构造函数
function Plan(color){
this.color=color;
}
//父类原型加个方法
Plan.prototype.fly=function(){
console.log('flying');
}
//子类
function Fighter(){
this.bullets=[]
}
Fighter.prototype=new Plan('red')
Fighter.prototype.constructor=Fighter; //纠正constructor
Fighter.prototype.shoot=function(){ //给子类添加子类特有的方法,注意顺序要在继承之后
console.log('biu biu biu')
}
var fighter1 = new Fighter()
~~~
原型链实现的继承主要有几个问题:
1、**共享**带来的问题,本来我们为了构造函数属性的封装私有性,方法的复用性,提倡将属性声明在构造函数内,而将方法绑定在原型对象上,但是现在子类的原型是父类的一个实例,自然父类的属性就变成子类原型的属性了;
这就会带来一个问题,我们知道构造函数的原型属性在所有构造的实例中是共享的,所以原型中属性的改变会反应到所有的实例上,这就违背了我们想要属性私有化的初衷;
2、创建子类的实例时,**不能**向父类的构造函数传递**参数**
为了解决以上两个问题,有一个叫借用构造函数的方法
只需要在子类构造函数内部使用apply或者call来调用父类的函数即可在实现属性继承的同时,又能传递参数,又能让实例不互相影响
3.constructor指向问题
结合借用构造函数和原型链的方法,可以实现比较完美的继承方法,可以称为**组合继承。**
~~~
//父类构造函数
function Plan(color){
this.color=color;
}
Plan.prototype.fly=function(){
console.log('flying');
}
//子类
function Fighter(color){
Plan.call(this,color); //继承属性
this.bullets=[];
}
Fighter.prototype=new Plan() //继承方法
Fighter.prototype.constructor=Fighter;
Fighter.prototype.shoot = function(){
console.log('biu biu biu');
}
var fighter1 = new Fighter('blue')
fighter1.shoot()
fighter1.fly()
~~~
还有一个**最佳实践**,用一个函数来copy父类的方法
~~~
//父类构造函数
function Plan(color){
this.color=color;
}
Plan.prototype.fly=function(){
console.log('flying')
}
//子类
function Fighter(color){
this.bullets=[];
Plan.call(this,'red') //继承属性
}
inheritPrototype(Fighter,Plan) //继承原型上的方法
//声明inheritPrototype 方法用于继承原型上的方法
function inheritPrototype(subType,superType){
var protoType=Object.create(superType.prototype);
protoType.constructor=subType;
subType.prototype=protoType;
}
var fighter=new Fighter()
fighter.fly()
~~~
- 以专业工程师的标准要求自己
- JS
- 函数的this
- 函数的argument
- 函数的apply、bind、call方法
- 创建对象
- 构造函数创建对象
- 原型结合构造函数创建对象
- 原型
- 继承
- 闭包
- 正则表达式
- Ajax
- 设计模式
- ES6
- es6的模块化
- 定义变量的新方式
- 函数扩展
- 数组扩展
- 性能与工程化
- 关于http与缓存
- 重排(reflow、layout)与重绘
- 页面性能
- gulp
- webpack
- 一些项目回顾总结
- 移动端&微信H5游戏
- 微信小程序
- Vue.js
- 随手记录
- 如何通过前端技能获取2018世界杯门票
- jsonp
- es6 javascript对象方法Object.assign()
- 一份不错的基础面试题
- vscode常用插件
- koroFileHeader
- 构建自己的Js工具库
- H5 game
- Phaser从入坑到放弃再入坑
- 1.游戏的创建
- 2.资源的加载
- 3.phaser中的舞台,世界和摄像机
- 4.游戏缩放控制,移动端的适配
- 5.phaser中的显示对象
- 1.概述
- 2.phaser中的图片,图形,和按钮
- 3.phaser中的精灵
- 4.文字
- 5.组
- 6.phaser中的动画
- 7.粒子和瓦片地图
- 8.瓦片地图
- lodash
- ES5 to ESNext — here’s every feature added to JavaScript since 2015
- 防抖(debounce) 和 节流(throttling)