原型链继承
继承就是让子类继承父类的属性和方法
//父类
function A(x) {
this.x = x
}
A.prototype.getX = function () {
console.log(this.x);
}
//子类
function B(y) {
this.y = y
}
B.prototype = new A(100);
B.prototype.constructor = B;
B.prototype.getY = function () {
console.log(this.y);
}
let b = new B(200);
b.x = 1000
console.log(b.x);//1000
console.log(b);
特点:原型链继承就是让子类原型属性指向父类的实例,实例想要调用这些方法,其实是基于查找原型链的机制查找完成
目的是可以让子类的实例能够使用父类的属性和方法
子类可以重写父类上的属性和方法
call继承
//父类
function A(x) {
this.x = x;
this.f = function () {
console.log("呵呵");
}
}
A.prototype.getX = function () {
console.log(this.x);
}
let a = new A(100);
console.log(a);//A {x: 100, f: ƒ}
// 子类
function B(y, x) {
this.y = y;
A.call(this, x);
}
B.prototype.getY = function () {
console.log(this.y);
}
let b = new B(200, 100);
console.log(b)//{y: 200, x: 100, f: ƒ}
在子类内,使用call()调用父类方法把父类的this修改为子类的this。让父类在子类函数里再次执行子类也拥有了父类的实例属性
特点:父类的私有的属性和方法 都会变成子类私有的属性和方法
子类只能继承父类的私有属性
组合式继承
结合原型链继承和借用构造函数继承的方法;
//父类
function A(x) {
this.x = x;
this.f = function () {
console.log("呵呵");
}
}
A.prototype.getX = function () {
console.log(this.x);
}
//子类
function B(y, x) {
this.y = y;
A.call(this, x);
}
B.prototype = new A(100);
B.prototype.constructor = B;
B.prototype.getY = function () {
console.log(this.y);
}
let b = new B(200, 100);
console.log(b);
(call继承)
1.子类实例可以使用父类私有的属性和方法
2.父类私有的属性和方法都会变成子类实例私有的属性和方法
(原型链继承)
3.子类实例可以通过原型链访问和使用父类公有的属性和方法
4.子类的原型链上会存在一份多余的父类的私有属性和方法
寄生组合继承
结合原型链继承和call继承的方法,需要自己创建一个对象,并且让这个对象的原型指向父类构造函数的prototype.实现寄生组合继承
//父类
function A(x) {
this.x = x
this.say = function () {
console.log('kin');
}
}
A.prototype.getX = function () {
console.log("getX", this.x);
}
let a = new A(100)
console.log(a);//A {x: 100, say: ƒ}
// 子类
function B(y, x) {
A.call(this, 666)
this.y = y
}
B.prototype = {}
B.prototype = Object.create(A.prototype)
B.prototype.constructor = B
B.prototype.getY = function () {
console.log("getY", this.y);
}
let b = new B(200)
console.log(b);//B {x: 666, y: 200, say: ƒ}
特点:父类私有的属性和方法,成为子类实例私有的属性和方法。
父类公有的属性和方法,成为子类实例公有的属性和方法。
ES6中的Class类和继承
// 父类
class A {
constructor(x) {
this.x = x
this.f = function () {
console.log('呵呵');
}
}
a = "张三"
getX() {
console.log(this.x);
}
}
// 公有属性
A.prototype.a = "李四"
let a = new A(100)
console.log(a);//A {a: 111, x: 100, say: ƒ}
// 子类
class B {
constructor(y) {
this.y = y
A.call(this)//Class constructor A cannot be invoked without 'new' class声明的构造函数(类) 不能当作普通函数执行
}
getY = function () {
console.log(this.y);
}
}
// 在使用Class构造类的时候 没办直接重定向子类原型
console.log(B.prototype = new A(100));//A {a: 111, x: 100, say: ƒ}
ES6中新增了一个定义类的方法 这样就不用我们手动的创建构造函数了
特点: 1.父类私有的属性和方法 会变成子类私有的属性和方法 2.父类公有属性和方法 会变成子类公有的属性和方法