1、原型链继承
原型链继承:原型链继承就是将父类的实例对象赋值给子类的原型对象。
不足:
1、如果父类有引用类型,子类一改,会导致后续的都改了
2、子的constructor指向父类,这是不对的,应该指向自己的构造函数
// 父类
function Student() {
this.job = '学生';
this.ah = ['游戏', '睡觉', '找平头妹'];
}
Student.prototype.showJob = function () {
console.log(this.job);
}
// 子类
function SmallStudent(name) {
this.name = name;
}
// 原型链继承就是将父类的实例对象赋值给子类的原型对象。
// 如何用一句话实现继承:将父的实例赋给子的原型(有不足)。
// 不足
// 1、如果父类有引用类型,子类一改,会导致后续的都改了
// 2、子的constructor指向父类,这是不对的,应该指向自己的构造函数
SmallStudent.prototype = new Student();
var s1 = new SmallStudent('小花');
console.log(s1);
// console.log(s1.job);
// console.log(s1.ah);
// console.log(s1.name);
// s1.showJob();
s1.ah.push('学习'); // 添加一项,会导致后面创建的都有这一项
var s2 = new SmallStudent('小黄');
console.log(s2);
console.log(s2.ah);
console.log(s2.constructor);
// 每一个函数都有原型对象,原型对象下面有一个constructor又指向构造函数
// function fn() { }
// console.log(fn.prototype);
// console.log(fn.prototype.constructor); // 指向构造函数
2、对象冒充继承
好处:解决了父类引用类型子类一改全改的问题
不足:只能继承父类构造函数中的属性,不能继承父类原型上的方法
// 父类
function Student() {
this.job = '学生';
this.ah = ['游戏', '睡觉', '找平头妹'];
}
Student.prototype.showJob = function () {
console.log(this.job);
}
// 子类
function SmallStudent(name) {
Student.call(this);
this.name = name;
}
// 对象冒充继承:在子类的构造函数中,调用父类的构造函数,并用call改this指向为子的实例
// 好处:解决了父类引用类型子类一改全改的问题
// 不足:只能继承父类构造函数中的属性,不能继承父类原型上的方法
var s1 = new SmallStudent('zs');
console.log(s1);
s1.ah.push('学习');
console.log(s1.name);
console.log(s1.job);
console.log(s1.ah);
var s2 = new SmallStudent('ls');
console.log(s2.ah);
3、组合继承
对象冒充继承属性
原型链继承方法
// 父类
function Student() {
this.job = '学生';
this.ah = ['游戏', '睡觉', '找平头妹'];
}
Student.prototype.showJob = function () {
console.log(this.job);
}
// 子类
function SmallStudent(name) {
Student.call(this); // 对象冒充继承
this.name = name;
}
SmallStudent.prototype = new Student(); // 原型链继承(会将父的方法和属性都继承过来)
var s1 = new SmallStudent('zs');
console.log(s1);
console.log(s1.job);
console.log(s1.ah);
console.log(s1.name);
s1.showJob();
// 组合继承(对象冒充+原型链)
// 问题:
// 1、同样的属性,在原型链中会出现多次
// 2、两次调用父的构造函数
// 父类
function Student() {
this.job = '学生';
this.ah = ['游戏', '睡觉', '找平头妹'];
}
Student.prototype.showJob = function () {
console.log(this.job);
}
// 寄生组合继承(是我们继承的标准方法)
// 将属性和方法分开继承。属性利用冒充继承,方法利用原型链继承
// 子类
function SmallStudent(name) {
Student.call(this); // 冒充继承,继承属性
this.name = name; // 再添加自己的
}
inherits(SmallStudent, Student); // 原型链继承,仅仅只继承方法
// 添加自己的方法,一定要写在继承方法的后面
SmallStudent.prototype.showName = function () {
console.log(this.name);
}
var s1 = new SmallStudent('zs');
console.log(s1);
console.log(s1.job);
console.log(s1.ah);
console.log(s1.name);
s1.showJob();
s1.showName();
console.log(s1.constructor);
function inherits(child, parent) {
var F = function () { };
F.prototype = parent.prototype;
child.prototype = new F();
child.prototype.constructor = child;
}