JS 是如何实现继承的
1、原型链
基本思想:利用原型让一个引用类型继承另外一个引用类型的属性和方法。
原型链算是实现继承的一个简单又比较好理解的一个方法了,对于原型链不理解的可以先去看看彻底理解 JS 的原型和原型链。具体实现如下:
<script>
function Parent(){
this.a = 66;
this.arr = [11];
}
function Children(){
}
Children.prototype = new Parent();//核心
var child1 = new Children();
var child2 = new Children();
console.log(child1.a);//66
console.log(child2.a);//66
//修改基本数据类型
child2.a = 88;
console.log(child1.a);//66
console.log(child2.a);//88
//修改引用类型
child2.arr.push(22);
console.log(child1.arr);//[11,22]
console.log(child2.arr);//[11,22]
</script>
可以看出用原型链实现继承时,要是有多个对象对同一个属性进行修改,而且这个属性还是引用类型,容易造成全部对象的那个属性都被迫修改了,即子类实例共享父类引用属性。还不可以向父类传参。
2、借用构造函数
<script>
function Parent(){
this.arr = [11];
this.fun = function (){
//...
}
}
function Children(){
Parent.call(this);//核心
}
var child1 = new Children();
var child2 = new Children();
console.log(child1.arr);//[11]
console.log(child2.arr);//[11]
//只修改child2
child2.arr.push(66);
console.log(child1.arr);//[11]
console.log(child2.arr);//[11,66]
//函数
console.log(child1.fun() === child2.fun()); //false
</script>
可以看出解决了子类实例共享父类引用属性的问题,此方法还可以在 call 中向父类进行传参。但是无法实现函数复用,每个子类实例都持有一个新的fun函数,太多了就会影响性能,内存爆炸。
3、组合继承
<script>
function Parent(){
this.arr = [11];
}
//在此处声明函数
Parent.prototype.fun = function (){};
function Children(){
Parent.call(this);//核心
}
Children.prototype = new Parent(); //核心
var child1 = new Children();
var child2 = new Children();
console.log(child1.fun() === child2.fun()); //true
</script>
把实例函数都放在原型对象上,以实现函数复用。同时还要保留借用构造函数方式的优点,通过Super.call(this);继承父类的基本属性和引用属性并保留能传参的优点;通过Sub.prototype = new Super();继承父类函数,实现函数复用。但是子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上的,又是内存浪费,
4、使用 ES6 的 class 关键字
<script> class Parent{ constructor(){ this.a = 66; this.b = 'luck'; } method(){ console.log('我是父类的方法'); } } class child extends Parent{ constructor() { super(); } method() { super.method(); } } const per = new child(); console.log(per) console.log(per.method()); </script>


浙公网安备 33010602011771号