浅析JavaScript实现基于原型对象的“继承”

2018-03-21 09:27沈浅
电脑知识与技术 2018年3期
关键词:继承

沈浅

摘要: 概述JavaScript实现继承的机制,对比基于类的继承,通过实例说明原型继承的特点,提出一个改进的“寄生组合模式”,使读者实现原型继承变得游刃有余。

关键词:JavaScript;原型继承;构造函数;原型对象

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2018)03-0091-02

Abstract: Overview the JavaScripts implementation of the mechanism on the inheritance, compare to Based on the class of inheritance, explain the prototype of inheritances characteristics through examples, propose an improved “parasitic combination mode”, and enable the readers to realize the prototype of inheritance become to do a job with skill and ease.

Key words: JavaScript, prototype of inheritance, constructor, prototype of object

1 概述

JavaScript是面向Web的编程语言,其高端、动态以及面向对象的编程风格,使得JavaScript已经从一门简单的脚本语言进化成为一门强大的编程语言,其基于原型的继承风格,使用起来非常灵活、高效,但对于初学者,要准确理解原型对象及其继承机制还是比较困难,本文就JavaScript原型继承的方式进行了介绍,并结合实例进行分析。

2 基于类的继承

首先,面向对象编程语言是基于类的语言,以Java为例,Java是基于类的语言,在基于类的语言中,对象是类的实例,并且一个类可以从另一个类继承。那么,在这些基于类的语言中,实现继承的好处:1)提高代码重用性高。如果我们新创建的类与已有的类有绝大部分相类似,则没有必要再重新定义这个完整的类。这样做可以实现代码的重用,大大减少了软件开发的成本。2)继承可以实现面向对象的“多态”特性。程序员可以将子类的对象直接赋值给父类的引用,无需再编写显式的类型转化。既减轻了工作量又保证了类型系统在安全上的优势。如例1所示代码,这是Java中实现继承的语法,class B从class A继承,子类B的对象就继承了父类A的所有非私有化成员。

3 基于原型的继承

3.1 原型对象

在JavaScript中,类的所有实例对象都从同一个原型对象上继承属性。因此,原型对象是其核心。早期使用一种所谓的“工厂模式”,即通过定义函数返回一个新创建的对象,后者继承自某个原型对象。如例2所示代码,函数inherit( )返回了一个继承自原型对象p的新对象。此种方法并不常用,JavaScript还可以通过构造函数来创建并初始化对象,只不过JavaScript没有类定义和特殊的构造器定义,需要程序员自己定义一个构造函数来创建属性,而所有的函数都可以被用来定义构造函数。如例3所示代码,在JavaScript中,只要创建一个新函数,就会根据一组特定规则为该函数创建一个prototype属性,而这个属性指向函数的原型对象。在默认情况下,原型对象会自动获得一个constructor属性,而这个属性包含一个指向prototype属性所在函数对象的指针。当一个函数对象被创建时,function构造器产生的函数对象会运行代码:“this.prototype = {constructor: this};”。

如图1所示,展现了构造函数,原型对象以及实例对象之间的关系。实例对象f指向原型对象p,与构造函数F没有直接的关系。在代码中,通过测试也发现实例对象雖然没有属性sayHi,但我们却可以调用f.sayHi( ),这说明新对象的这些属性和方法是所有实例共享的。

3.2 原型继承的问题及改进

基于原型的继承,功能强大,一般采用原型链继承方式,但也存在弊端。构造函数的prototype属性是一个指针,它可以是特定类型的所有实例共享的属性和方法。如果我们在对象f中对原型对象p的某个属性进行修改,则会影响到其他实例。这个显然不行,我们可以通过构造函数,将不想被共享的属性定义在构造函数中,而将需要共享的部分放在原型对象中。这种方式称为“寄生组合模式”。该模式既避免了原型链中实例共享属性的问题,又实现了构造函数无法实现的继承模式,是JavaScript中比较常用的方式。如例4所示代码,Father构造函数模拟“父类”,Son构造函数模拟“子类”,代码Son.prototype=new Father( );实现原型继承,父类对象的所有属性都可被子类所有对象共享。在创建子类实例对象时,程序会先去Son的构造函数去找对象的属性,如果找不到,则去子类继承的原型对象中去查找,如果还是没有找到,则去原型对象继承的父类中去查找,直到找到Object对象,如果还是没有,就报错。

4 结束语

其实JavaScript并没有提供所谓的类继承,但是我们可以通过一种原型方式实现,并且实现方法是灵活多样的,不存在哪种更优,根据不同的需求实现不同方式的继承。深入理解JavaScript中实现继承的原理,即原型及原型链的问题,只要理解了这些,实现继承就可以变得游刃有余。

参考文献:

[1] David Flanagan.JavaScript权威指南[M]. 6版.北京:机械工业出版社,2012,201-217.

[2] 王贯飞.JavaScrip中基于原型的继承的实现与分析[J].计算机光盘软件与应用,2014(3):110-111.

猜你喜欢
继承
鲁迅小说对传统文学艺术的继承和创新
浅谈杜审言、杜甫的祖孙关系:推崇、继承、发展