概述
在讲几种继承方式的优缺点之前,先给大家介绍一下在javascript中对各种属性的分类
在javascript中,数据分为简单数据和复杂数据,简单数据在对象里称为基本属性,而数组,函数在对象里称为引用属性(数组,函数其实都是对象)
对此不太清楚的,可以参考我之前的博客 javascript数据类型
下面具体介绍一下在对象里各种属性的分类
function Fun(){
// 私有属性
var val = 1; // 私有基本属性
var arr = [1]; // 私有引用属性
function fun(){} // 私有函数(引用属性)
// 实例属性
this.val = 1; // 实例基本属性
this.arr = [1]; // 实例引用属性
this.fun = function(){}; // 实例函数(引用属性)
}
// 原型属性
Fun.prototype.val = 1; // 原型基本属性
Fun.prototype.arr = [1]; // 原型引用属性
Fun.prototype.fun = function(){}; // 原型函数(引用属性)
在看此篇博客之前,需要先看一下我的上一篇博客 javascript原型继承(第四篇)—几种继承方式,且要看懂里面的内容。
在看懂上一篇的基础上,再来看这篇,便没有什么难度了,而我的本意也就是用这篇写一下上一篇里各个继承方式的优缺点。
一、原型链继承
function Super(){
this.val = 1;
this.arr = [1];
}
function Sub(){
// ...
}
Sub.prototype = new Super(); // 核心
Sub.prototype.constructor = Sub;
var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val); // 2
alert(sub2.val); // 1
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1, 2
优点:
1.简单,易于实现
缺点:
1.修改sub1.arr后sub2.arr也变了,因为来自原型对象的引用属性是所有实例共享的。
(原因:执行sub1.arr.push(2);先对sub1进行属性查找,找遍了实例属性(在本例中没有实例属性),没找到,就开始顺着原型链向上找,拿到了sub1的原型对象,一搜身,发现有arr属性。于是给arr末尾插入了2,所以sub2.arr也变了)
2.创建子类实例时,无法向父类构造函数传参
二、构造函数继承
原型链很简单,可是存在2个致命缺点简直不能用。于是,便有了这个构造函数继承,
function Super(val){
this.val = val;
this.arr = [1];
this.fun = function(){
// ...
}
}
function Sub(val){
Super.call(this, arguments); // 核心
// ...
}
var sub1 = new Sub(1);
var sub2 = new Sub(2);
sub1.arr.push(2);
alert(sub1.val); // 1
alert(sub2.val); // 2
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1
alert(sub1.fun === sub2.fun); // false,因为sub1和sub2各自拥有fun,它们的内存地址是不同的
优点:
1.解决了子类实例共享父类引用属性的问题
2.创建子类实例时,可以向父类构造函数传参
缺点:
1.无法实现函数复用,每个子类实例都持有一个新的fun函数,如果实例太多,会造成内存大量被占用
三、组合继承
目前,我们的构造函数继承仍旧有问题,所以便产生了组合继承
function Super(){
// 只在此处声明基本属性和引用属性
this.val = 1;
this.arr = [1];
}
// 在此处声明函数
Super.prototype.fun = function(){};
//Super.prototype.fun3...
function Sub(){
Super.call(this); // 核心
// ...
}
Sub.prototype = new Super(); // 核心
var sub1 = new Sub(1);
var sub2 = new Sub(2);
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val); // 2
alert(sub2.val); // 1
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1
alert(sub1.fun === sub2.fun); //true
优点:
1.不存在引用属性共享问题
2.创建子类实例时,可以向父类构造函数传参
3.函数可复用
缺点:(一点小瑕疵,但仍旧不影响它是现在最常用的继承方式)
1.子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上的。
最后,javascript原型继承到此就告一段落了,其实还有在js中还有很多继承方式,不过我觉得了解并掌握了上述三种继承方式,已经足够纵横天下了。
参考了相关博客梦烬–重新理解js继承方式
最后
以上就是追寻导师为你收集整理的javascript原型继承(第五篇)---几种继承方式的优缺点的全部内容,希望文章能够帮你解决javascript原型继承(第五篇)---几种继承方式的优缺点所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复