(放一放,有空重新整理)
继承前,首先当然要有一个父类(Father)
// 父类 Father
function Father(name = "father") {
// 属性
this.name = name;
// 实例方法
this.sleep = function () {
console.log(this.name + '在睡觉');
}
}
// 原型方法
Father.prototype.look = function (lookType) {
console.log(this.name + "在看" + lookType);
}
-
1 - 原型继承
核心:将父类的实例作为子类的原型(并不是把父类中的属性和方法克隆一份一模一样的给子类,而是让子类和父类之间增加了原型链接)。
特点:子类原型会继承父类中所有的属性和方法,不管是公有的还是私有的。子类的实例也是父类的实例。
/* 原型继承 */
function Son(name, age) {
this.name = name;
this.age = age;
}
Son.prototype = new Father() // 相当于重写 Son 原型
Son.prototype.constructor = Son // 必要!把 Son 原型上的 constructor 重新指向Son
let son = new Son("son", 11)
console.log(son.name); // son
console.log(son.age); // 11
son.sleep(); // son在睡觉
son.look("TV"); // son在看TV
-
2 - call 继承(构造继承)
核心:在子类的内部调用父类,通过 call 改变父类中的 this 指向,使用父类的构造函数来增强子类实例,相当于将父类的实例属性复制给子类。
特点:可以继承父类的属性和实例方法,但是无法继承原型中的方法。子类的实例只是例子的实例,并不是父类的实例。
/* call 继承(原型继承) */
function Son(name, age) {
Father.call(this)
this.name = name
this.age = age
}
let son = new Son("son", 11)
console.log(son.name); // son
console.log(son.age); // 11
son.sleep() // son在睡觉
son.look("TV") // 报错 - son.look is not a function
-
3 - 冒充对象继承
核心:定义一个中间对象来完成子类对父类方法对拷贝
特点:因为是子类是将父类对属性和方法全部拷贝,所以每个子类都有父类方法(实例方法和原型方法)。
/* 冒充对象继承 */
function Son(name, age) {
let temp = new Father()
for (let k in temp) {
this[k] = temp[k]
}
this.name = name
this.age = age
temp = null
}
let son = new Son("son", 11)
console.log(son.name); // son
console.log(son.age); // 11
son.sleep() // son在睡觉
son.look("TV") // son在看TV
-
4 - 组合继承
核心:结合原型继承和构造继承
特点:即是子类实例,也是父类继承。且函数可复用,不会造成方法过载。
/* 组合继承 */
function Son(name, age) {
Father.call(this)
this.name = name;
this.age = age;
}
Son.prototype = new Father()
Son.prototype.constructor = Son
let son = new Son("son", 11)
console.log(son.name); // son
console.log(son.age); // 11
son.sleep() // son在睡觉
son.look("TV") // son在看TV