作用
主要作用是实现方法和属性的复用
方法一 父类构造函数法
通过调用父类的构造函数来使得子类继承父类的属性和方法
缺点 => 只 继承了 父类实例的相关属性和方法 原型对象上的属性和方法没有继承
javascript">function Cat(name, age) {
this.name = name;
this.age = age;
}
Cat.prototype.say = function () {
console.log("喵喵喵");
}
function blueCat(name, age) {
//Cat() 如果直接这样调用,则构造函数里面的this将会指向window
Cat.call(this, name, age);
//通过call函数强制将构造函数Cat的this指向blueCat创建的实例化对象
}
let tom = new blueCat("Tom", "3");
console.dir(tom);
上面案例便是通过调用父类构造函数来继承父类的属性和方法,由于构造函数里面的this总是指向该构造函数所创建的实例化对象,所以子类通过call方法将父类的this也指向子类的实例化对象,但实例化子类对象时发现say()这个定义在Cat原型对象里面的方法并未被继承到
方法二 父类原型链赋值法
通过将父类的原型链复制到子类上进行继承。
缺点 => 引用同一个内存空间 只要有一个改动 另一个也会被修改
javascript"> function Cat(name, age) {
this.name = name;
this.age = age;
}
Cat.prototype.say = function () {
console.log("喵喵喵");
}
let haha = new Cat("HaHa", "1");
function blueCat(name, age, area) {
this.area = area;
}
//将父类的原型链浅复制给子类
blueCat.prototype = Cat.prototype;
blueCat.prototype.say = function () {
console.log("Playing the piano");
}
let tom = new blueCat("Tom", "3", "USA");
blueCat.prototype.say();
Cat.prototype.say();
当改变blueCat对象的say方法时,cat对象也会改变。
方法三 父类实例对象原型链法
为了补足方法二的缺陷,方法三将原本父类原型链直接复制给子类变成,创建父类实例化对象后,再将实例化的对象的原型链复制给子类,这样子类改变原型对象里面的方法时(有点方法重写的意思)就不会影响父类了。
javascript"> function Cat(name, age) {
this.name = name;
this.age = age;
}
Cat.prototype.say = function () {
console.log("喵喵喵");
}
let catObj = new Cat("haha", "2");
function blueCat(area) {
this.area = area;
}
blueCat.prototype = catObj;
blueCat.prototype.say = function () {
console.log("Playing the piano");
}
let tom = new blueCat("USA");
blueCat.prototype.say();
Cat.prototype.say();
但是这样还是有问题,只能继承父类 原型对象上的属性和方法 => 实例的相关属性和方法无法继承,但是实例的属性放到了原型对象上。
可以看到子类blueCat没有继承到name和age反而将其放到了原型对象上了。
最终版 中间件法
通过拓宽原型链,达到继承父类原型对象方法的目的 (用父类实例化对象 覆盖子类的原型对象 => 要原型链)
javascript">
function Cat(name, age) {
this.name = name;
this.age = age;
}
Cat.prototype.say = function () {
console.log("喵喵喵");
}
let ha = new Cat("haha", "1");
function blueCat(name, age, area) {
//通过调用构造函数将实例化属性继承
Cat(this, name, age);
this.name = name;
this.age = age;
this.area = area;
}
//利用中间件做媒介,将原型对象继承给子类
function Fn() { }
Fn.prototype = Cat.prototype;
blueCat.prototype = new Fn();
//给子类对象强制定义constructor指向自己,否则实例化对象的constructor会和Fn里面的一样
blueCat.prototype.constructor = blueCat;
blueCat.prototype.say = function () {
console.log("Playing the piano");
}
let tom = new blueCat("name", "2", "USA");
console.dir(tom);
extends
以上的方法都是es5之前的继承方式,es6引入了class模块。如同java、c++、、、这类语言一样的类定义。
javascript">
class Cat {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
class blueCat extends Cat {
constructor(name, age, area) {
super(name, age, area);
this.name = name;
this.age = age;
this.area = area;
}
say() {
console.log("喵喵喵");
}
}
let tom = new blueCat("Tom", "2", "USA");
console.log(tom);
这样使得继承变得更为简单