JavaScript基于原型链的继承

 更新时间:2016年6月24日 10:00  点击:1860

Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承。

原型链是JavaScript中继承的主要方法。

原型链的基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法。

构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

如果让原型对象等于另一个对象的实例,这样原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。

实现原型链的基本模式:

function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
};
function SubType() {
this.subproperty = false;
}
// 继承SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); // true 

SubType继承了SuperType,继承是通过创建SuperType的实例,并将该实例赋给SubType.prototype实现的。实现的本质是重写原型对象,换成一个新类型的实例。这样,原来存在于SuperType的实例中的属性和方法,也存在与SubType.prototype中了。然后给SubType.prototype添加一个方法,这样就继承了SuperType的属性和方法的基础上又添加了一个方法。

上例中的实例关系表示如下:

上面没有使用SubType默认提供的原型,而是给它换了一个新原型;这个新原型就是SuperType的实例。新原型内部还有一个执行SuperType的原型的指针。结果变成了instance指向SubType的原型,SubType的原型又指向SuperType的原型。getValue()方法仍然还在SuperType.prototype中,但prototype则位于SubType.prototype中。这是因为property是一个实例属性,而getSuperValue()则是一个原型方法。既然SubType.prototype现在是SuperType的实例,那么property自然位于该实例中。

注意:instance.constructor现在指向的是SuperType,因为SubType的原型指向了另一个对象——SuperType的原型,这个原型对象的constructor属性指向的是SuperType。

当以读取模式访问一个属性时,首先会在实例中搜索该属性。如果没有找到该属性。则会继续搜索实例的原型。通过原型链实现继承的情况下,搜索过程就得以沿着原型链继续向上。

默认的原型

所有引用类型都默认继承了Object,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object的实例。因此默认原型都会包含一个内部指针,指向Object.prototype。这就是为什么自定义类型都会继承toString()、valueOf()等方法的原因。

完整的原型链:

在上面的继承体系中,SubType继承了SuperType,SuperType继承了Object。当调用了instance.toString()时,实际调用的是保存在Object.prototype中的那个方法。

确定实例和原型的关系

可以通过两种方式来确定原型和实例之间的关系:

使用instanceof操作符

alert(instance instanceof Object);
alert(instance instanceof SuperType);
alert(instance instanceof SubType); 

由于原型链的关系,上面全部返回true。

使用isPrototypeOf()方法

alert(Object.prototype.isPrototypeOf(instance));
alert(SuperType.prototype.isPrototypeOf(instance));
alert(SubType.prototype.isPrototypeOf(instance)); 

谨慎定义方法

给原型添加方法的代码一定要放在替换原型的语句之后。

function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
};
function SubType() {
this.subproperty = false;
}
SuperType.prototype = new SuperType();
// 添加方法
SubType.prototype.getSubValue = function () {
return this.subproperty;
};
// 覆盖超类中的方法
SubType.prototype.getSuperValue = function () {
return false;
};
var instance = new SubType();
alert(instance.getSuperValue()); // false 

上面的例子必须注意的是,在用SuperType的实例替换原型之后,再定义那两个方法。

另外,在通过原型链实现继承时,不能使用该对象字面量创建原型方法。因为这样做会重写原型链:

function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function () {
return this.property;
};
function SubType() {
this.subproperty = false;
}
// 继承SuperType
SubType.prototype = new SuperType();
// 使用字面量添加新方法,导致上一行代码无效
SubType.prototype = {
getSubValue :function() {
return this.subproperty;
},
someOtherMethod: function () {
return false;
}
};
var instance = new SubType();
alert(instance.getSuperValue()); // error 

上例将SuperType的实例赋值给原型,紧接着又将原型替换成一个对象字面量而导致的问题。现在的原型包含一个Object的实例,而非SuperType的实例,SubType和SuperType之间已经没有关系了。

原型链的问题

前面已经介绍过,包含引用类型值得原型属性会被所有实例共享;而这也正是为什么要在构造函数中,而不是在原型对象中定义属性的原因。

function SuperType() {
this.colors = ["red", "blue", "green"];
}
function SubType() {
}
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors); // "red", "blue", "green", "black"
var instance2 = new SubType();
alert(instance2.colors); // "red", "blue", "green", "black" 

在上面的例子中,SuperType构造函数中定义了一个colors属性,该属性包含一个数组,SuperType的每个实例都会有各自包含自己数组的colors属性。当SubType通过原型链继承了SuperType之后,SubType.prototype就变成了SuperType的一个实例,所以它也拥有了一个它自己的colors属性。但是,SubType的所有实例都会共享这一个colors属性。

另一问题是,没有办法在不影响所有对象实例的情况下,给超类的构造函数传递参数。

以上所述是小编给大家介绍的JavaScript基于原型链的继承 的相关知识,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

[!--infotagslink--]

相关文章

  • JavaScript判断浏览器及其版本信息

    本篇文章主要分享了通过window.navigator来判断浏览器及其版本信息的实例代码。具有一定的参考价值,下面跟着小编一起来看下吧...2017-01-23
  • js实现浏览器打印功能的示例代码

    这篇文章主要介绍了js如何实现浏览器打印功能,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-15
  • 利用JS实现点击按钮后图片自动切换的简单方法

    下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • 详解前端安全之JavaScript防http劫持与XSS

    作为前端,一直以来都知道HTTP劫持与XSS跨站脚本、CSRF跨站请求伪造。防御这些劫持最好的方法是从后端入手,前端能做的太少。而且由于源码的暴露,攻击者很容易绕过防御手段。但这不代表我们去了解这块的相关知识是没意义的,本文的许多方法,用在其他方面也是大有作用。...2021-05-24
  • JavaScript仿支付宝密码输入框

    那么今天我就用JavaScript代码来实现这个效果吧,那么首先介绍一下整个的思路,首先我们先将确定输入密码的位数,我的需求是5位,那么就用一个div标签包住5个input标签...2016-01-02
  • js+css实现回到顶部按钮(back to top)

    这篇文章主要为大家详细介绍了js+css实现回到顶部按钮back to top回到顶部按钮,感兴趣的小伙伴们可以参考一下...2016-03-03
  • js实现上传图片及时预览

    这篇文章主要为大家详细介绍了js实现上传图片及时预览的相关资料,具有一定的参考价值,感兴趣的朋友可以参考一下...2016-05-09
  • 一个关于JS正则匹配的踩坑记录

    这篇文章主要给大家介绍了一个关于JS正则匹配的踩坑记录,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-04-13
  • Nest.js参数校验和自定义返回数据格式详解

    这篇文章主要给大家介绍了关于Nest.js参数校验和自定义返回数据格式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-28
  • 如何使用JavaScript实现无缝滚动自动播放轮播图效果

    这篇文章主要介绍了如何使用JavaScript实现“无缝滚动 自动播放”轮播图效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-08-20
  • node.js如何操作MySQL数据库

    这篇文章主要介绍了node.js如何操作MySQL数据库,帮助大家更好的进行web开发,感兴趣的朋友可以了解下...2020-10-29
  • js屏蔽F12审查元素,禁止修改页面代码等实现代码

    有时候我们需要屏蔽客户端的F12,以防菜鸟也可以随意修改我们的代码,也处于源码的保护等操作,这里就为大家分享一下常见的代码...2020-10-03
  • 基于JavaScript实现文字超出部分隐藏

    这篇文章主要介绍了基于JavaScript实现文字超出部分隐藏 的相关资料,需要的朋友可以参考下...2016-03-01
  • js组件SlotMachine实现图片切换效果制作抽奖系统

    这篇文章主要介绍了js组件SlotMachine实现图片切换效果制作抽奖系统的相关资料,需要的朋友可以参考下...2016-04-19
  • js实现列表按字母排序

    这篇文章主要为大家详细介绍了js实现列表按字母排序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-11
  • NodeJS实现阿里大鱼短信通知发送

    本文给大家介绍的是nodejs实现使用阿里大鱼短信API发送消息的方法和代码,有需要的小伙伴可以参考下。...2016-01-20
  • js实现调用网络摄像头及常见错误处理

    这篇文章主要介绍了js实现调用网络摄像头及常见错误处理,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-07
  • JS创建Tag标签的方法详解

    这篇文章主要介绍了JS创建Tag标签的方法,结合具体实例形式分析了javascript动态操作页面HTML元素实现tag标签功能的步骤与相关操作技巧,需要的朋友可以参考下...2017-06-15
  • JS实现随机生成验证码

    这篇文章主要为大家详细介绍了JS实现随机生成验证码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-06
  • node.JS md5加密中文与php结果不一致怎么办

    这次文章要给大家介绍的是node.JS md5加密中文与php结果不一致怎么办,不知道具体解决办法的下面跟小编一起来看看。 因项目需要,需要Node.js与PHP做接口调用,发现nod...2017-07-06