JavaScript-继承的多种的方式

有异议或者理解不对的地方欢迎指出

首先
先定义父类:
定义父类,并在父类的原型上添加方法
在这里插入图片描述

一:原型链继承

子类实例的原型等于父类的实例,从而继承父类构造函数的属性.构造函数方法,原型方法,原型属性.
但是原型属性是子类共同使用的.如果修改了,其他子类会受到影响.另外实例无法向构造函数传参.

function PersonOne(){
}
PersonOne.prototype= new Person(“asd”,12);
var personone=new PersonOne(“sum1”);
personone.proto.proto.sex=“123”;
console.log(personone.name,personone.age);
console.log(personone.sex);
personone.setAge();
personone.printName();
console.log(personone,"&&&&");
var persontwo=new PersonOne();
console.log(persontwo.name,persontwo.age);
console.log(persontwo.sex)
persontwo.printName();
console.log(persontwo);
输出:
在这里插入图片描述
想要避免这种情况,可以使用借用构造函数实现,也可以重新new新的子类去继承父类
在这里插入图片描述
这样除了父类原型属性共享外,构造参数实现了私有化.在这里插入图片描述

二:借用构造函数实现继承

通过借助call/apply来改变this的指向,从而构造独有的作用域,每个实例继承属性私有化,相互之间不影响.
缺点:构造方法无法复用,每个实例有携带一个构造方法.
function PersonOne(){
Person.call(this,arguments);
}
PersonOne.prototype= new Person();
var personone=new PersonOne(“tom”,“123”);
var persontwo=new PersonOne(“Jack”,“456”);
console.log(personone);
console.log(persontwo);
console.log(personone.setAge === persontwo.setAge)
console.log(personone.printName === persontwo.printName)
输出:
在这里插入图片描述

三:组合继承

把方法放到父类的原型上,实现复用.例如上述的printName方法,唯一不足的是父类构造函数调用两次,子类实例上会覆盖子类原型上的.

四:原型继承

通过在中间生成对象,使用中间对象去继承父类,最后接收生成的新对象.
f
核心:
(1)function create(obj){
var F = function(){};
F.prototype = obj;
return new F();
}
用法:var person=new Person();
var proto=create(person);
不足:原型引用的属性会被实例共享,而且无法实现复用.

五:寄生组合继承

相对于来说较为完善.(Es6提供Object.create创造新对象的方法);
function Person(name,age){
this.name=name;
this.age=age;
this.setAge=function(){
console.log(this.age);
}
}
Person.prototype.printName=function(){
console.log(this.name);
}
Person.prototype.sex=“1”;
function PersonOne(){
Person.call(this,arguments);
}
//继承父类原型上的属性和方法,相比之前create去掉了多余的父类实例的属性
var proto=Object.create(Person.prototype);
//将生成的proto新对象与PersonOne进行关联,相当于PersonOne实例化的实例.
proto.constructor=PersonOne;
//关联原型,实例化后proto具有父类的构造属性,方法,原型的方法,属性
PersonOne.prototype=proto;

自己在编写的时候,发现这个问题.
function Person(){
this.name=“parent”
this.arr=[1,2];
}
Person.prototype.printName=function(){
console.log(this.name);
}

 function PersonOne(){

 }

 PersonOne.prototype=new Person();
 var person=new PersonOne();
 person.name="2";
 person.arr.push(4)

 console.log(person)

 var per2=new PersonOne();

 console.log(per2)

在这里插入图片描述
name属性在实例上实例化,但是arr却并没有实例化,愿意在于arr为引用类型,在赋值的时候实例会随着原型链找到arr的位置并修改值(arr在堆上的地址是唯一的).而name是String类型,所以不能直接修改值,需要通过实例化生成对象,从而修改值.每一个实例化的对象在栈上的位置不同,具有私有化.

部分参考该文章:https://www.cnblogs.com/ayqy/p/4471638.html

猜你喜欢

转载自blog.csdn.net/qq_36082247/article/details/89097501