JS原型链与几种继承方法的对比

继承的方式有两种:接口继承、实现继承
接口继承:即虚函数,父类只定义接口,不具体实现
子类继承接口,自己负责实现这个方法,运行时动态决定
调用哪个实现。
实现继承:父类实现的方法,子类可以直接调用

JS中只支持实现继承,以原型链来实现。

回顾一下构造函数、原型、实例的关系:
每个构造函数都有一个原型对象,
原型对象又都包含一个constructor指针指向构造函数,
实例包含一个_proto_内部属性指向原型对象。

继承的实现方法(父类型叫Parent,子类型叫Child)
原本Child.prototype = Child自己的原型对象,
现在如果将Child.prototype = Parent的实例,
那么Parent实例的属性以及Parent所指向的原型对象的方法,
也可以通过Child的实例访问到。
function Parent(name){
this.name = name;
}
Parent.prototype.getParentName(){
return this.name;
}

function Child(name){
this.name = name;
}
Child.prototype = new Parent("parent");

Child.prototype.getChildName(){
return this.name;
}

var child1 = new Child("child");
alert(child1.getChildName()); //child
alert(child1.getParentName()); //parent

getcParentName()在原型链里的搜索过程:
1、child1实例里有没有这个方法?没有
2、child1的原型对象中有没有?即Parent的实例中,有没有这个方法?没有
3、那Parent的原型对象中有没有这个方法?有,则执行这个方法

其实这并不是原型链的最顶端,所有引用类型都继承了Object,所有函数的默认的
prototype都指向Object的实例。
所以Parent.prototype = Object的实例,
也正是因为如此,所有的函数都可以使用
toString、valueOf、hasOwnProperty、isPrototypeOf等函数,它们都是
Object.prototype中的方法

原型链的问题:
1、子类无法独占父类的引用属性
父类的引用类型,比如一个数组,是单独一份,每个子类的实例访问到的都是同一份,
修改它会反映到所有子类的实例上。
2、无法在不影响其他子类对象的基础上,给父类的构造函数传参
子类继承父类时,“可以给父类的构造函数传参”,但是所有子类都会被影响,如下:
Child.prototype = new Parent("parent");
所有的Child的实例,其Parent的name都叫“parent”。

越讲越感觉JS这个继承,好鸡肋

为了克服以上2个问题,又引出了其他几种基于原型链的继承方法(好复杂= =|)

1、借用构造函数(伪造对象/经典继承)
function Parent(name){
this.name = name;
}

function Child(){
Parent.call(this,"parent");
this.age = 24;
}
这个方法,就尼玛像c语言里面的宏一样,把父类的构造函数里执行的语句抠出来,
在子类里执行一遍,于是子类就会有一个name属性,值是“parent”。
缺点:方法都在构造函数里,不可见,无法复用

2、组合继承(伪经典继承)
function Parent(name){
this.name = name;
this.colors = ["blue","yellow","green"];
}

function Child(name,age){
Parent.call(this,name);
this.age = age;
}

Child.prototype = new Parent();
Child.prototype.sayAge = function(){
alert(this.age);
}
可以看出是结合了上述两种方法,
在原型链的基础上,借用构造函数解决了上述两种问题,
使得子类可以给父类传参,又保证了每个实例拥有自己的属性
这种方法比较常用

3、原型式继承
function object(o){
function F(){};
F.prototype = o;
return new F();
}

这种继承没有构造函数,返回一个对象,这个对象的prototype
指向实例o。
ES5新增了Object.create()方法,规范了原型式继承。
这种方法和原型链方法类似,但是更精简一些,用于在已有一个
对象的基础上,要构建另一个与之相似的对象,可以新增方法,
或者覆盖原对象的属性。不过引用类型还是共享的

时间: 2024-10-24 20:08:23

JS原型链与几种继承方法的对比的相关文章

js oop中的三种继承方法

JS OOP 中的三种继承方法: 很多读者关于js opp的继承比较模糊,本文总结了oop中的三种继承方法,以助于读者进行区分. <继承使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方法.(继承的两方,发生在两个类之间)> 一.通过object实现继承 1:定义父类 function Parent(){} 2:定义子类 funtion Son(){} 3:通过原型给Object对象添加一个扩展方法. Object.prototype.customExtend = function(p

深入理解JS原型链与继承

我 觉得阅读精彩的文章是提升自己最快的方法,而且我发现人在不同阶段看待同样的东西都会有不同的收获,有一天你看到一本好书或者好的文章,请记得收藏起来, 隔断时间再去看看,我想应该会有很大的收获.其实今天要讨论的主题,有许多人写过许多精彩的文章,但是今天我还是想把自己的理解的知识记录下来.我在学习 掌握JS原型链和继承的时候,就是看得@阮一峰老师的写的文章,觉得他写的技术类的文章都容易让理解,简明概要,又好理解.他是我学习JS路程里面一个比较佩服的导师,昨天重新看了他写的<Javascript 面向

js原型链与继承(初体验)

js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型是否与Object.prototype相等来证明是否存在obj的原型,答案返回true,所以存在.然后我们定义一个函数foo(),任何一个函数都有它的prototype对象,即函数的原型,我们可以在函数的原型上添加任意属性,之后通过new一个实例化的对象可以共享

浅谈js原型链与继承

js原型链与继承是js中的重点,所以我们通过以下三个例子来进行详细的讲解. 首先定义一个对象obj,该对象的原型为obj._proto_,我们可以用ES5中的getPrototypeOf这一方法来查询obj的原型,我们通过判断obj的原型是否与Object.prototype相等来证明是否存在obj的原型,答案返回true,所以存在.然后我们定义一个函数foo(),任何一个函数都有它的prototype对象,即函数的原型,我们可以在函数的原型上添加任意属性,之后通过new一个实例化的对象可以共享

js 原型链和继承(转)

在理解继承之前,需要知道 js 的三个东西: 什么是 JS 原型链 this 的值到底是什么 JS 的 new 到底是干什么的 1. 什么是 JS 原型链? 我们知道 JS 有对象,比如 var obj = { name: "obj" }; 我们通过控制台把 obj 打印出来: 我们会发现 obj 已经有几个属性(方法)了.那么问题来了:valueOf / toString / constructor 是怎么来?我们并没有给 obj.valueOf 赋值呀. 上面这个图有点难懂,我手画

简单粗暴地理解js原型链--js面向对象编程

简单粗暴地理解js原型链--js面向对象编程 原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧,想点与代码无关的事,比如人.妖以及人妖. 1)人是人他妈生的,妖是妖他妈生的.人和妖都是对象实例,而人他妈和妖他妈就是原型.原型也是对象,叫原型对象. 2)人他妈和人他爸啪啪啪能生出一堆人宝宝.妖他妈和妖他爸啪啪啪能生出一堆妖宝宝,啪啪啪就是构造函数,俗

JS 原型链图形详解

JS原型链 这篇文章是「深入ECMA-262-3」系列的一个概览和摘要.每个部分都包含了对应章节的链接,所以你可以阅读它们以便对其有更深的理解. 对象 ECMAScript做为一个高度抽象的面向对象语言,是通过对象来交互的.即使ECMAScript里边也有基本类型,但是,当需要的时候,它们也会被转换成对象. 一个对象就是一个属性集合,并拥有一个独立的prototype(原型)对象.这个prototype可以是一个对象或者null.* 让我们看一个关于对象的基本例子.一个对象的prototype是

JavaScript面向对象(二)——成员属性、静态属性、原型属性与JS原型链

前  言 上一篇博客(https://www.cnblogs.com/qdjianghao/p/10177360.html )中,我们介绍了JS中的面向对象,并详细的解释了this的指向问题.本篇博客,我们继续来学习JS的面向对象.来深入理解一下JavaScript OOP中的成员属性/方法.静态属性/方法.原型属性/方法,并且一起来探讨一下JS中的原型与原型链. 一 成员属性与成员方法 在构造函数中,通过this.属性声明.或者实例化出对象后,通过"对象.属性"追加的.都属于成员属性

Apache和Nginx防盗链的几种配置方法

要实现防盗链,我们就必须先理解盗链的实现原理,提到防盗链的实现原理就不得不从HTTP协议说起,在HTTP协议中,有一个表头字段叫 referer,采用URL的格式来表示从哪儿链接到当前的网页或文件.换句话说,通过referer,网站可以检测目标网页访问的来源网页,如果是资源 文件,则可以跟踪到显示它的网页地址.有了referer跟踪来源就好办了,这时就可以通过技术手段来进行处理,一旦检测到来源不是本站即进行阻止或者返 回指定的页面. Nginx防盗链的配置 1.nginx针对文件类型的防盗链配置