前言
在ES6中,继承是依靠类来实现的,但是在ES5中,实现继承的方式依靠原型链完成,相对于ES6比较复杂一点,先来看看ES6中的继承的写法
ES6的类的写法
在ES6的中,子类可以继承父类的方法和属性,这里的父类(确切来说是超类)为Box,子类Ball继承父类Box的方法和属性,必须在构造函数constructor中写super()才可以继承
class Box{
constructor(){
}
play(){
}
}
class Ball extends Box{
constructor(){
super();
}
}
es5的类的写法
function Box(_r){
this.r=_r;
console.log("aa");
}
Box.a=3;//相当于es6中的静态属性
Box.run=function(){
console.log(Box.a);//相当于es6的静态方法
}
Box.prototype.b=10;//相当于es6中的动态属性
Box.prototype.play=function(){//相当于es6中的动态方法
console.log(this.b);
}
var b=new Box(3);
console.log(b) //{r:3,__proto__:{b:10,play:f(),constructor:f(),__proto:{}}}
如果设置原型属性和方法时,以对象的形式写的话,就会覆盖掉原本的原型链,这样就会少了constructor
function Box(_r){
this.r=_r;
console.log("aa");
}
Box.a=3;
Box.run=function(){
console.log(Box.a);
}
Box.prototype={
b:10,
play:function(){
console.log(this.b);
}
}
Box.prototype.b=10;
Box.prototype.play=function(){
console.log(this.b);
}
var b=new Box(3);
console.log(b) //{r:3,__proto__:{b:10,play:f(),__proto:{}}}; //少了constructor
}}}
如果以对象的形式写,并且不会覆盖原有的__proto__,则需要重新定义constructor为当前类的构造函数,并且这个构造函数不可以修改,不可以遍历,不可以删除
- 如果是基类,可以直接这样写,但是后面还必须重新定义constructor为当前类的构造函数
- 如果不是基类,就不能直接使用prototype重设置对象
function Box(_r){
this.r=_r;
console.log("aa");
}
Box.a=3;
Box.run=function(){
console.log(Box.a);
}
Box.prototype={
b:10,
play:function(){
}
}
Object.defineProperty(Box.prototype,"constructor",{
value:Box
})
var b=new Box(3);
console.log(b);
ES5继承
1、组合式继承,把父类的实例化对象放在子类的原型下
超类的构造函数被执行两遍,这种继承适合于超类的构造函数中没有任何语句
new Box(3)执行一遍Box构造函数,Box.call(this,_r)又执行一遍
function Box(_r) {
this.r = _r;
console.log("aa");
}
Box.a = 3;
Box.run = function () {
console.log(Box.a);
}
Box.prototype.b = 10;
Box.prototype.play = function () {
console.log(this.b);
}
function Ball(_r){
//冒充
Box.call(this,_r);//执行Box构造函数 把Box里的this替换成Ball的this,这叫冒充
}
Ball.prototype=new Box(3);//new Box(3)是实例化对象 Ball.prototype是子类的原型
var c=new Ball(10);
console.log(c);
2、原型继承
这种方式就不用执行两遍超类的构造函数,但是一遍都没执行,只完成了原型的继承
将Box的原型赋值给F的原型,F类没有Box的构造函数
function Box(_r) {
this.r = _r;
console.log("aa");
}
Box.a = 3;
Box.run = function () {
console.log(Box.a);
}
Box.prototype.b = 10;
Box.prototype.play = function () {
console.log(this.b);
}
function F(){
}
F.prototype=Box.prototype;
function Ball(){
}
Ball.prototype=new F();
var b=new Ball();
console.log(b);
3、Object.create
这种继承写法只能用于IE9以上浏览器,这种继承写法中,执行一遍超类的构造函数,也完成了原型的继承。
function Box(_r) {
this.r = _r;
console.log("aa");
}
Box.a = 3;
Box.run = function () {
console.log(Box.a);
}
Box.prototype.b = 10;
Box.prototype.play = function () {
console.log(this.b);
}
function Ball(_r){
Box.call(this,_r)
}
Ball.prototype=Object.create(Box.prototype);
var b=new Ball(10);
console.log(b);
4、寄生式继承
function Box(_r) {
this.r = _r;
console.log("aa");
}
Box.a = 3;
Box.run = function () {
console.log(Box.a);
}
Box.prototype.b = 10;
Box.prototype.play = function () {
console.log(this.b);
}
function Ball(_r){
// super();
this.superClass.apply(this,arguments);
}
Ball.prototype.walk=function(){
console.log("walk");
}
extend(Ball,Box);
Ball.prototype.play=function(){
// super.play();
this.superClass.prototype.play.apply(this,arguments);
console.log("执行完成")
}
var b=new Ball(10);
// console.log(b);
b.play();
function extend(subClass,supClass){
function F(){}
F.prototype=supClass.prototype;
// subClass.prototype=new F();
// Object.assign(subClass.prototype,new F());
var o=subClass.prototype;
subClass.prototype=new F();
// 复制原来的原型下的所有内容
if(Object.assign){
// 如果Object.assign可以使用时
Object.assign(subClass.prototype,o);
}else{
// Object.getOwnPropertyNames可以使用时
if(Object.getOwnPropertyNames){
var names=Object.getOwnPropertyNames(o);
for(var i=0;i<names.length;i++){
Object.defineProperty(subClass.prototype,names[i],Object.getOwnPropertyDescriptor(names[i]));
}
}else{
for(var prop in o){
subClass.prototype[prop]=o[prop]
}
}
}
subClass.prototype.constructor=subClass;
subClass.prototype.superClass=supClass
if(supClass.prototype.constructor===Object){
supClass.prototype.constructor=supClass;
}
}
可以直接封装
function Ball(_r){
// super();
this.superClass.apply(this,arguments);
}
Ball.prototype.walk=function(){
console.log("walk");
}
Ball.extend_1(Box);
Ball.prototype.play=function(){
this.superClass.prototype.play.apply(this,arguments);
console.log("执行完成")
}
var b=new Ball(10);
b.play();