JavaScript继承体系的深入浅出
一、构造器的原型属性与原型对象
刚接触js时通常依样画瓢,用函数new一个实例,也不知道其原因,只听说js中函数即对象。原来js中没有采用Java等语言中的类继承体系,而是使用原型对象(prototype)实现继承体系,具体说是利用“构造器”实现类的功能。
首先解释下原型继承中的两个重要概念:原型属性、原型对象(实例)。
就js对象系统而言,创建的每个函数(构造器)都有一个prototype原型属性,同时,通过构造器创建的每个对象实例也包含一个_proto_属性,prototype和_proto_属性是一个指针,指向原型对象。普通函数与构造函数的唯一区别就是,其原型属性prototype是不是一个有意义的值。
原型属性prototype所指向的原型是一个对象实例(Object instance)。具体如下图所示,若构造器Animal()有一个原型对象B,则由该构造器创建的实例都必然复制于B。即:Animal()的实例a1的_proto_属性也会指向原型对象B。因此,实例a1能够继承B的所有属性、方法和其他性质。
图1 js对象实例化实现
二、空的对象
在javascript中,“空的对象”是整个原型继承体系的根基,是所有对象的基础。介绍“空的对象”之前,必须先介绍下“空对象(null)”。
空对象null
null不是“空的对象”,作为javascript中的一个保留字,其含义是:
(1)属于对象类型
(2)对象是空值
作为一个对象类型,可以使用for…in去列举它,但是作为一个空值,null没有任何方法和属性(包括constructor、_proto_等属性),因此列举不到任何内容。如下例所示:
var num=0; for(var propertyName in null) { num++; }
Alert(num);//显示值为0
最重要的一点是null没有原型,它并不是自Object()构造器(或其子类)实例化而来,对其进行instanceof 运算会返回false。
2.“空的对象”
“空的对象”是指一个标准的、通过Object()构造的对象实例。例如:
obj=new Object();或 obj={};
“空的对象”具有“对象”的一切特性,因此可以存取toString()、valueof等预定义的属性和方法。
3.“空的对象”与null的关系
如下图2中红线所示路径,当通过”Object.prototype._proto_”获取Object原型对象的-proto-属性时,将会得到”null”,由于null对象没有任何属性,也就是说”Object {}”
原型对象就是原型链的终点了。
图2 js类继承体系
三、Javascript继承的实现以及原型链维护
(1)继承的实现
第一节说过javascript中类继承是通过修改构造函数的原型属性prototype实现的。如下代码所示:
function Animal() { this.name = 'Animal'; }; function Dog() { }; Dog.prototype = new Animal(); var d = new Dog(); console.log(d.name);//'Animal'
通过创建一个Animal类型的实例并将其赋值给构造函数Dog()的prototype属性,从而实现类型继承,即Animal是Dog的父类。这样Dog类型的实例d也能访问Animal类型的name属性。
(2)原型链
JS对象继承体系中有两种原型链:“内部原型链”和“构造器原型链”。如图3所示,黑色箭头指示路径是通过构造函数的prototype属性保持的“构造器原型链”。红色箭头指示路径是通过对象实例的_proto_属性保持的“内部原型链”。
图3 原型链
(3)原型链维护
图3说明构造器通过显示的prototype构建了一个原型链,而对象实例也通过_ proto _属性构建了一个原型链。由于_ proto _是一个不可访问的内部属性(Chrome中可以查看对象_ proto _属性的值,但不可以修改),因此无法从子类(Dog)的实例dog1开始访问整个原型链。因此,我们需要从图3中的“内部原型链”和“构造器原型链”中找到一个连接点,使得实例不能访问obj._proto_的情况下通过构造器访问内部原型链(将两种原型链串联起来)。
若要从子类的实例开始访问整个原型链,需要使用实例的constructor属性维护原型链。
其实,JavaScript已经为构造器维护了原型属性,根据如下测试代码,当我们自定义一个构造器时,其原型对象是一个Object()类型的实例,但是其原型对象的constructor属性默认总是指向构造器自身,而非指向其父类Object。如图4中构造器实例中蓝色框中的constructor属性,该constructor属性继承自原型对象,因此可以得出一个自定义的构造器产生的实例,其constructor属性默认总是指向该构造器。
function Animal() { }; var a = new Animal(); console.log(Animal.prototype);//Object(){} console.log(Animal.prototype.constructor === Animal);//true//true
图4
因此,在_proto_属性不可访问时,可通过a1.constructor.prototype获取实例a1的原型对象。然而,当我们自定义一个构造函数Dog(),并且手动指定其prototype属性值为Animal,即指定Dog的父类为Animal。此时访问d1.constructor值为Animal,而不是Dog;由图5可以看出,Dog的原型对象和dog分别由Animal()和Dog()两个不同的构造器产生,然而他们的constructor属性指向了相同的构造器(Animal),这样就与使用constructor属性串联两种原型链的设想冲突了。
图5
是构造器出问题还是原型出了问题?图5可以看出,原型继承要求的“复制行为”已经正确实现,能够从子类实例中访问原型对象属性,问题是在给子类构造器Dog()赋予一个原型对象时应该“修正”该原型对象的构造属性值(constructor)。ECMAScript 3标准提供的方法是:保持原型的构造器属性,在子类构造器中初始化其实例对象的构造属性。代码如下:
function Dog () { //初始化constructor属性 this.constructor=Dog; //或 this.constructor=arguments.callee; }; Dog.prototype = new Animal();//赋予原型对象,实现继承
图6
对constructor属性“修正”后效果如图6所示,在子类构造器Dog中初始化其实例对象的constructor属性后,Dog的实例对象的constructor都指向Dog,而Dog的原型对象的constructor仍然指向父类型构造器Animal。这样就可以实现利用constructor属性串联起原型链,可以从子类实例开始回溯整个原型链。
总结
以上是JavaScript继承体系的深入浅出的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

人脸检测识别技术已经是一个比较成熟且应用广泛的技术。而目前最为广泛的互联网应用语言非JS莫属,在Web前端实现人脸检测识别相比后端的人脸识别有优势也有弱势。优势包括减少网络交互、实时识别,大大缩短了用户等待时间,提高了用户体验;弱势是:受到模型大小限制,其中准确率也有限。如何在web端使用js实现人脸检测呢?为了实现Web端人脸识别,需要熟悉相关的编程语言和技术,如JavaScript、HTML、CSS、WebRTC等。同时还需要掌握相关的计算机视觉和人工智能技术。值得注意的是,由于Web端的计

股票分析必备工具:学习PHP和JS绘制蜡烛图的步骤,需要具体代码示例随着互联网和科技的快速发展,股票交易已经成为许多投资者的重要途径之一。而股票分析是投资者决策的重要一环,其中蜡烛图被广泛应用于技术分析中。学习如何使用PHP和JS绘制蜡烛图将为投资者提供更多直观的信息,帮助他们更好地做出决策。蜡烛图是一种以蜡烛形状来展示股票价格的技术图表。它展示了股票价格的

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

随着互联网金融的迅速发展,股票投资已经成为了越来越多人的选择。而在股票交易中,蜡烛图是一种常用的技术分析方法,它能够显示股票价格的变化趋势,帮助投资者做出更加精准的决策。本文将通过介绍PHP和JS的开发技巧,带领读者了解如何绘制股票蜡烛图,并提供具体的代码示例。一、了解股票蜡烛图在介绍如何绘制股票蜡烛图之前,我们首先需要了解一下什么是蜡烛图。蜡烛图是由日本人
