Posted in Javascript onMarch 31, 2021
我们可以简单的分为以下几种继承方式:
- 原型链继承
- 构造函数继承
- 组合继承
- 寄生组合继承/加强版寄生组合继承
- 类继承
以下 A代表父级 B代表子级
我们先看原型链继承
先上代码
function A(name,age){
this.name = name;
this.arr = [];
this.age = age;
this.sing = function(){
return '我会唱歌、我会跳舞。'
}
}
function B(run){
this.run = run
}
B.prototype = new A('zjq',18)
console.log(new B()._proto_ === A.construct)
let a = new B('123')
let b = new B('456')
a.arr.push('1')
console.log(b.arr) //['1']
B已经完全的集成到了A的属性和方法,但是有一个缺点就是当我们实例化两个B的时候,给第一个arr添加item,第二个实例化对象也会跟着变化。a和b的arr都新添了一个item。方法变成了共享,不是实例所私有的。(引用类型)
构造函数继承
上代码
function A(name,age){
this.name = name;
this.age = age;
this.arr =[];
this.sing = function(){
return '我会唱歌、我会跳舞。'
}
}
A.prototype.zjq = function(){
return 'run'
}
function B(run){
this.run = run
A.call(this,'zjq',this.run) //父级的属性和方法称为子级的私有属性和方法 子级可以向父级传参
}
let Bobj = new B('runing')
console.log(Bobj)
console.log(Bobj.sing())
let a = new B('123')
let b = new B('456')
a.arr.push('1')
console.log(b.arr) //[]
构造函数继承虽然可以使用A中的方法和属性,但是不是继承的关系过来的,它的_proto_上没有A的任何信息,它将A的属性和方法变成了自己的属性和方法,但是原型链上的方法(zjq方法并没有)是无法继承到的。创建子类实例,可以向父类构造函数传参数。解决了方法变成了共享的问题,变成了实例所私有的。
组合继承
上代码
function A(name, age) {
this.name = name;
this.age = age;
this.arr=[]
}
A.prototype.sing = function () {
return '我会唱歌、我会跳舞。' + this.name + this.age
}
function B(run) {
this.run = run
A.call(this, 'zjq', this.run) //父级的属性和方法称为子级的私有属性和方法 子级可以向父级传参
}
B.prototype = new A()
let brr = new B('参数')
let a = new B('123')
let b = new B('456')
a.arr.push('1')
console.log(b.arr) //[]
console.log(brr)
console.log(brr.sing())
console.log(brr.age)
结合原型链继承和借用构造函数继承的优点 ,继承了A的属性和方法也可以向A传递自己的参数。解决了方法变成了共享的问题,变成了实例所私有的,但是A构造函数被调用了两次。
寄生组合继承
上代码
function A(name, age) {
this.name = name;
this.age = age;
this.arr = []
}
A.prototype.sing = function () {
return '我会唱歌、我会跳舞。' + this.name + this.age
}
function B(run) {
this.run = run
A.call(this, 'zjq', this.run)
}
B.prototype = A.prototype
// let b= new B('123')
// console.log(b)
B.prototype.sing = function () {
return 'xxx'
}
let a = new B('123')
let b = new B('456')
a.arr.push('1')
console.log(b.arr) //[]
console.log(new A().sing()) //变成了xxx 而不是 return '我会唱歌、我会跳舞。' + this.name + this.age
解决了方法变成了共享的问题,变成了实例所私有的,但是又有一个突出的问题,B可以改变原型链上的东西,A和B共享了原型链。
加强版寄生组合继承
function A(name, age) {
this.name = name;
this.age = age;
}
A.prototype.sing = function () {
return '我会唱歌、我会跳舞。' + this.name + this.age
}
function B(run) {
this.run = run
A.call(this, 'zjq', this.run)
}
function f(){}
f.prototype = A.prototype
B.prototype = new f()
let b= new B('123')
console.log(b)
B.prototype.sing = function(){
return 'xxx'
}
console.log(new A().sing()) //return '我会唱歌、我会跳舞。' + this.name + this.age
解决了共享原型链的问题。 完美收官。
类继承
上代码
class A {//父级构造函数
constructor(name) {
this.name = name;
}
sing() {
return this.name + 'xxx'
}
}
class B extends A { //子级继承父级
constructor(name,age) {
super(name) 调用实现父类的构造函数 并传递参数
this.age = age
}
}
let b = new B(12333,222) //实例化子级
console.log(b)
console.log(b.sing()) //return this.name + 'xxx'
JS继承最简单的理解方式
- Author -
六卿声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。
Reply on: @reply_date@
@reply_contents@