JavaScript 类式继承与原型继承
2015-10-23 18:44
609 查看
交叉着写Java和Javascript都有2年多了,今天来总结下自己所了解的Javascript类与继承。
Javascript本身没有类似Java的面向对象的类与继承术语,但其基于原型对象的思想却可以轻松实现各种类和继承。
下面来描述实现类的第一种方法,请看例子:
从形式上看上去,与面向对象的类几乎一样,this为实例化后的对象自身,name/age为成员变量,say为成员方法,但其内部原理却相差甚远。
接下来分析其中的不同之处,先看一下代码:
按照面向对象语言的特征,表面上看上去people_1/2都有自己的属性name/age,有公共的(占用同一份内存区域)方法say,但在JS中并非如此。
首先,People自身是一个对象,new People产生了两个对象people_1/2,每个对象都拥有各自的内存空间,即将name/age/say在各自空间都存在一份。
可通过 people_1.say == people_2.say 验证,结合下图可清楚得出结论,每个对象之间是独立的个体,没有关联关系。
接下来,结合JS原型概念构造类的第二种方法。原型是JS的核心概念,后续篇章详细描述。
通过看到上述代码结果,可得出people_1/2共享成员say,可通过下图分析。这里涉及到了原型链的概念,后面和原型一起阐明。
关于类的构造就介绍到这。接下来描述实现继承的几种方法。
先来看第一种,基于类式继承的方式。
这种继承基于第一种类的构造形式,即采用复制的方法实现子类对象对父类成员的继承。
其中,起复制作用的关键在与People.call(this,...)语句上,意思是使用call方法借用People函数来构造Man对象。
这里不太好理解,首先要理解call方法如何使用,其次要了解this作用域的概念和使用。关于作用域及作用域链概念也在以后的篇章中阐述。
总之,这里的意义是将People对象的属性复制到Man对象上。
我们看下这里的图形描述:
很显然man/woman都继承了People的成员变量,但其采用的是复制的方法,对象之间并没有建立真正的继承。
接下来将基于第二种构造类的方法来介绍第二种构造类的形式,即继承依赖原型。直接看一下代码:
上面的代码可能已经引入一些JS原理层面的东西,还是先用图来展示:
上图中引入几个比较JS原理的东西,prototype/constructor/__proto__,其中前两者是JS标准中存在的,
而__proto__是标准中未暴露的,该名称采用chrome暴露的属性名。
其中prototype是原型函数,每个函数中都存在;constructor是构造器,每个对象都存在;__proto__是原型对象,每个对象都存在。
此处先介绍到这,后期将根据ECMAScript标准详细介绍几者之间的关系。
通过上面的线条可以了解每个对象之间的关系,以及原型链在其中所起的作用。
可以看出,第二种继承方法是基于原型的,虽然成员是采用复制的方式,但保证了方法的继承性。这与传统面向对象类继承意义上才是一致的。
通过上面的类的构造和继承方式,我们对Javascript原型继承有一定了解。那么如果要实现内部成员,内部方法,该如何实现呢?
疑问将在下个篇章解答。
Javascript本身没有类似Java的面向对象的类与继承术语,但其基于原型对象的思想却可以轻松实现各种类和继承。
下面来描述实现类的第一种方法,请看例子:
function People(name, age){ this.name = name; this.age = age; this.say = function(){ console.log('hello, javascript!'); }; } var people = new People('sky',25); people.say();
从形式上看上去,与面向对象的类几乎一样,this为实例化后的对象自身,name/age为成员变量,say为成员方法,但其内部原理却相差甚远。
接下来分析其中的不同之处,先看一下代码:
var people_1 = new People('sky1',21); var people_2 = new People('sky2',22); people_1.say == people_2.say//false
按照面向对象语言的特征,表面上看上去people_1/2都有自己的属性name/age,有公共的(占用同一份内存区域)方法say,但在JS中并非如此。
首先,People自身是一个对象,new People产生了两个对象people_1/2,每个对象都拥有各自的内存空间,即将name/age/say在各自空间都存在一份。
可通过 people_1.say == people_2.say 验证,结合下图可清楚得出结论,每个对象之间是独立的个体,没有关联关系。
接下来,结合JS原型概念构造类的第二种方法。原型是JS的核心概念,后续篇章详细描述。
function People(name,age){ this.name=name; this.age=age; } People.prototype.say = function(){ console.log('hello, javascript!'); }; var people_1 = new People('sky1',21); var people_2 = new People('sky2',22); people_1.say == people_2.say//true
通过看到上述代码结果,可得出people_1/2共享成员say,可通过下图分析。这里涉及到了原型链的概念,后面和原型一起阐明。
关于类的构造就介绍到这。接下来描述实现继承的几种方法。
先来看第一种,基于类式继承的方式。
function People(name,age,sex){ this.name=name; this.age=age; this.sex=sex; this.say=function(){ console.log('hello,javascript!'); }; } function Man(name,age){ People.call(this,name,age,'male'); } function Woman(name,age){ People.call(this,name,age,'female'); } var man = new Man('sky-man',21); var woman = new Woman('sky-woman',22); man.say(); woman.say();
这种继承基于第一种类的构造形式,即采用复制的方法实现子类对象对父类成员的继承。
其中,起复制作用的关键在与People.call(this,...)语句上,意思是使用call方法借用People函数来构造Man对象。
这里不太好理解,首先要理解call方法如何使用,其次要了解this作用域的概念和使用。关于作用域及作用域链概念也在以后的篇章中阐述。
总之,这里的意义是将People对象的属性复制到Man对象上。
我们看下这里的图形描述:
很显然man/woman都继承了People的成员变量,但其采用的是复制的方法,对象之间并没有建立真正的继承。
接下来将基于第二种构造类的方法来介绍第二种构造类的形式,即继承依赖原型。直接看一下代码:
function People(name,age,sex){ this.name=name; this.age=age; this.sex=sex; } People.prototype.say=function(){ console.log('hello,javascript!'); } function Man(name,age){ People.call(this,name,age,'male'); } Man.prototype = Object.create(People.prototype); function Woman(name,age){ People.call(this,name,age,'female'); } Woman.prototype = Object.create(People.prototype);
上面的代码可能已经引入一些JS原理层面的东西,还是先用图来展示:
上图中引入几个比较JS原理的东西,prototype/constructor/__proto__,其中前两者是JS标准中存在的,
而__proto__是标准中未暴露的,该名称采用chrome暴露的属性名。
其中prototype是原型函数,每个函数中都存在;constructor是构造器,每个对象都存在;__proto__是原型对象,每个对象都存在。
此处先介绍到这,后期将根据ECMAScript标准详细介绍几者之间的关系。
通过上面的线条可以了解每个对象之间的关系,以及原型链在其中所起的作用。
可以看出,第二种继承方法是基于原型的,虽然成员是采用复制的方式,但保证了方法的继承性。这与传统面向对象类继承意义上才是一致的。
通过上面的类的构造和继承方式,我们对Javascript原型继承有一定了解。那么如果要实现内部成员,内部方法,该如何实现呢?
疑问将在下个篇章解答。
相关文章推荐
- JSON和XML优缺点的比较
- js 程序执行与顺序实现详解
- js常用函数
- Tabris.js 介绍与学习<3>
- js 解析key值为数字的json的问题
- 102 seajs popup 兼容性问题
- JS判断移动设备最佳方法
- js面向对象编程(三)非构造函数的继承
- js面向对象编程(二)构造函数的继承
- 【Miaov】JS4-数据类型、类型转换
- 【前端学习】javascript面向对象编程(继承和复用)
- js 弹出确认 取消对话框
- JS获取指定年月天数
- java实现面向对象和javaScript基于对象的区别&java垃圾回收机制和其他编程语言的比较
- js面向对象编程(一):封装
- 你不知道的JavaScript--Item21 漂移的this
- 你不知道的JavaScript--Item21 漂移的this
- js中的for循环 写法的效率对比
- JS 如何实现两个div的内容调换
- JS正则表达式验证账号、手机号、电话和邮箱