es5 的继承

抄写文章https://www.jianshu.com/p/342966fdf816
es5利用原型链的特性来实现继承,将子类构造函数的原型做为父类构造函数的实例,原型链的特点就是逐层查找,从子类开始一直往上直到所有对象的原型Object.prototype,找到属性方法之后就会停止,所以下层的属性方法会覆盖上层
基于原型链的继承代码如下
function Super(){ this.flag = true; } Super.prototype.getFlag = function(){ return this.flag; } function Sub(){ this.subFlag = false; } Sub.prototype = new Super; Sub.prototype.getSubFlag = function(){ return this.subFlag; } var es5 = new Sub;
原型链实现继承的主要问题:
1.为了构造函数属性的封装私有性,方法的复用性,提倡将属性声明在构造函数内部,将方法绑定在原型对象上,但是现在子类的原型是父类的实例,自然父类的属性就变成了子类原型的属性了;这样带来一个问题,因为构造函数的原型属性在所有的构造实例中是共享的,所以原型属性的改变会反应到所有实例上,这就违背了属性私有化的初衷;
2.创建子类的实例时不能向父类的构造函数传递参数
function Super(){ this.flag = true; } function Sub(){ this.subFlag = false; } Sub.prototype = new Super; var obj = new Sub(); obj.flag = flase; //修改之后,由于是原型上的属性,之后创建的所有实例都会受到影响 var obj_2 = new Sub(); console.log(obj.flag) //false;
为了解决以上两个问题,有一个叫借用构造函数的方法
只需要在子类构造函数内部使用apply或者call来调用父类的函数即可在实现属性继承的同时,又能传递参数,又能让实例不互相影响
function Super(){ this.flag = true; } function Sub(){ Super.call(this) //如果父类可以需要接收参数,这里也可以直接传递 } var obj = new Sub(); obj.flag = flase; var obj_2 = new Sub(); console.log(obj.flag) //依然是true,不会相互影响
借用构造函数和原型链的方法,可以实现比较完美的的继承方法,可以称为组合继承:
function Super(){ this.flag = true; } Super.prototype.getFlag = function(){ return this.flag; //继承方法 } function Sub(){ this.subFlag = flase Super.call(this) //继承属性 } Sub.prototype = new Super; Sub.prototype.constructor = Sub; var obj = new Sub(); Super.prototype.getSubFlag = function(){ return this.flag; }
Sub.prototype = new Super; 会导致Sub.prototype的constructor指向Super;
然而constructor的定义是要指向原型属性对应的构造函数的,Sub.prototype是Sub构造函数的原型,所以应该添加一句纠正:
Sub.prototype.constructor = Sub;

你可能感兴趣的:(es5 的继承)