JavaScript 对象、函数和继承


Posted in Javascript onJuly 07, 2009

1、 Javascript中的对象

JavaScript可以说是一个基于对象的编程语言,为什么说是基于对象而不是面向对象,因为JavaScript自身只实现了封装,而没有实现继承和多态。既然他是基于对象的,那么我们就来说说js中的对象。有人说js中所有的都是对象,这句话不完全正确。正确的一方是他强调了对象在js中的重要性,对象在js中无处不在,包括可以构造对象的函数本身也是对象。但是另一方面,js中也有一些简单的数据类型,包括数字、字符串和布尔值、null值和undefined值,而这些不是对象。那为什么这些类型的值不是对象呢,毕竟他们也有方法。那让我们来看一下,JavaScript中对于对象的定义,有两种定义。

(1)JavaScript中的对象是可变的键控集合(keyed collections) (此定义来自老道的那本书的第三章)

(2)JavaScript中的对象是无序(unordered)的属性集合,这些属性可以含有简单的数据类型、对象、函数;保存在一个对象属性中的函数也被称为这个对象的方法。 (来自ECMA-262 的4.3.3)(注:这里所说的属性是可以在js脚本中创建和访问的(我们称之为显性属性),不包括系统为对象自动分配的内部属性)

那为什么那个简单的数据类型不是对象呢,主要是因为这些数据类型的值中拥有的方法是不可变的,而一个对象的属性是应当可以被改变的。

2、 对象中的原型链[[proto]]

JavaScript中的每个对象创建的时候系统都会自动为其分配一个原型属性[[proto]],用来连接到他的原型对象。在JavaScript中就是通过每个对象中的[[proto]]来实现对象的继承关系的。但是对象的[[proto]]属性在JavaScript是不能访问和修改的,他是作为一个内部的属性存在的,而且是在对象被创建的同时由系统自动设定的。

当访问一个对象的某一属性,如果这个属性在此对象中不存在,就在他的[[proto]]所指的原型对象的属性中寻找,如果找到则返回,否则继续沿着[[proto]]链一直找下去,直到[[proto]]的连接为null的时候停止。

3、 函数也是对象

JavaScript中的函数本身就是一个对象(所以我们经常称之为函数对象),而且可以说他是js中最重要的对象。之所以称之为最重要的对象,一方面他可以扮演像其他语言中的函数同样的角色,可以被调用,可以被传入参数;另一方面他还被作为对象的构造器(constructor)来使用,可以结合new操作符来创建对象。

既然函数就是对象,所以必然含有对象拥有的全部性质,包括对象在创建时设定的原型链[[proto]]属性。

让我们来看看函数对象和普通对象有什么区别。我们前面说过,对象就是无序的属性集合,那么函数的属性和普通对象的属性有什么不同呢。根据ECMA-262中的13.2节所述,在函数对象创建时,系统会默认为其创建两个属性[[call]]和[[constructor]],当函数对象被当做一个普通函数调用的时候(例如myFunc()),“()”操作符指明函数对象的[[call]]属性就被执行,当他被当做一个构造器被调用的时候(例如new myConst()),他的[[constructor]]属性就被执行,[[cosntructor]]的执行过程我们将在下一节中介绍。除此之外,当一个函数被创建时,系统会默认的再为其创建一个显示属性prototype,并为其赋值为

this.prototype = {constructor:this}

具体内容可以参加老道的那本书的第五章。这个函数对象的prototype属性也是为了js把函数当做构造器来实现继承是准备的,但是这个属性是可以在js脚本中访问和修改的。在这里要强调的一点是,大家一定要区分对象中的[[proto]]属性和函数对象中的prototype属性,我在刚开始学习的时候就是因为没有很好的区分这两个东西,走了很多的弯路。

4、 对象的创建

在js中有两种创建对象的方法,一种是通过字面量来实现,如

var Person = {

“first_name”:'liang',

‘last_name':'yang'

}

另一种方法是通过构造器来创建

var my = new Person(‘liang','yang');

其实第一种方式的创建过程相当于调用Object构造器来实现,如下。

var Person = new Object();

Person.first_name = ‘liang';

Person.last_name = ‘yang'

所以我们可以把js中所有对象的创建都合并到使用构造器来实现,下面我么来详细说明构造器创建对象的过程:

第一步,先创建一个空的对象(既没有任何属性),并将这个对象的[[proto]]指向这个构造器函数的prototype属性对象

第二步,将这个空的对象作为this指针传给构造器函数并执行

第三步,如果上面的函数返回一个对象,则返回这个对象,否则返回第一步创建的对象

第四步,把函数当做一个类来使用

由上面的步骤我们可以看出,一般来说函数对象的prototype指向的是一个普通对象,而不是一个函数对象,这个普通对象中的属在由此函数构造器创建的对象中也可以访问。由此可以如此设计我们的代码,假设一个函数就可以代表一个类,这个构造器函数生成的对象就是这个类的实例对象,那么实例对象中应有的属性和方法应该放在这个构造器函数的prototype中,这个类的静态方法就可以直接放到这个函数作为对象的属性中,最后这个函数体就是我们平时在面向对象语言中所说的构造函数(在这里我们要区分连个词“构造函数”和“构造器函数”,所谓构造函数是指普通的面向对象语言中的类的构造函数,而构造器函数是指javascript中的一个函数被当做构造器使用)。

在第3节我们说过每个函数的prototype对象中总是含有一个constructor属性,这个属性就是连接到我们的这个函数本身。再加之,有这个函数生成的每个对象的[[proto]]属性都是指向构造器函数的prototype对象,所以通过[[proto]]链,每个由构造器函数生成的对象,都有一个constructor属性,指向生成他的构造器函数,因此我们可以通过这个属性来判断这个对象是有哪个构造器函数生成的。

5、 函数继承(类继承)

说了这么多,终于到了我们可以在javascript中讨论继承的时候了,我们先来考虑一下要实现类的继承我们都要做些什么,假设我们要从superClass继承到子类subClass

为了使得由subClass生成的对象中能够访问superClass生成的对象中的属性,那么可以使subClass.prototype为一个superClass构造函数生成的对象。

subclass.prototye = new superClass();

但是问题来了,根据我们在第4节说的new superClass()不仅复制了superClass.prototype中的所有方法,而且还运行了superClass()这个函数,这个函数起到的作用是类中的构造函数。我们知道应该在子类的构造函数中调用父类的构造函数来实现初始化。为此我们可以创建一个构造函数为空的,但是原型和superClass原型一致的函数,并使subClass.prototype指向这个函数生成的对象。

var F = function() {};

F.prototype = superClass.prototype;

subClass.protptype = new F();

这样我们就可以再不调用构造函数的同时完成属性复制的工作。但是还有一个问题,那就是我们修改了subClass的prototype属性,从而也就删除了其中的constructor属性,这样我们就无法知道他是哪个构造器函数生成的对象了。我们可以再次给他赋值

subClass.prototype.constructor = subClass;

这样复制属性的问题就迎刃而解了。但是新的问题又出现了,在subClass中我们无法知道他的父类是哪个构造器函数,所以就无法在构造函数中调用父类的构造函数,为此我们可以为subClass添加一个属性,指明他的父类

subClass.superClass = superClass.prototype;

这样我么就可以在子类的构造函数中使用subClass.superClass.constructor来访问父类的构造函数了。最后我们把以上的思路写成一个函数

myPro.extend = function (subClass,superClass) {

var F = function() {};

F.prototype = superClass.prototype;

subClass.protptype = new F();

subClass.prototype.constructor = subClass;

subClass.superClass = superClass.prototype;

superClass.prototype.constructor = superClass;

}

Javascript 相关文章推荐
通用javascript脚本函数库 方便开发
Oct 13 Javascript
JavaScript 联动的无限级封装类,数据采用非Ajax方式,随意添加联动
Jun 29 Javascript
javascript中clipboardData对象用法详解
May 13 Javascript
js获取当前日期时间及其它日期操作汇总
Mar 08 Javascript
基于RequireJS和JQuery的模块化编程日常问题解析
Apr 14 Javascript
Bootstrap fileinput文件上传预览插件使用详解
May 16 Javascript
Angular 4 指令快速入门教程
Jun 07 Javascript
JavaScript仿微信(电话)联系人列表滑动字母索引实例讲解(推荐)
Aug 16 Javascript
JavaScript 通过Ajax 动态加载CheckBox复选框
Aug 31 Javascript
Vue.js上传图片到阿里云OSS存储的方法示例
Dec 13 Javascript
了解前端理论:rscss和rsjs
May 23 Javascript
js中复选框的取值及赋值示例详解
Oct 18 Javascript
js 日期转换成中文格式的函数
Jul 07 #Javascript
javascript 面向对象思想 附源码
Jul 07 #Javascript
jquery BS,dialog控件自适应大小
Jul 06 #Javascript
javascript 浏览器判断 绑定事件 arguments 转换数组 数组遍历
Jul 06 #Javascript
javascript 写类方式之十
Jul 05 #Javascript
javascript 写类方式之九
Jul 05 #Javascript
javascript 写类方式之八
Jul 05 #Javascript
You might like
全国FM电台频率大全 - 3 河北省
2020/03/11 无线电
php微信公众号开发之现金红包
2018/04/16 PHP
[推荐]javascript 面向对象技术基础教程
2009/03/03 Javascript
JS简单的图片放大缩小的两种方法
2013/11/11 Javascript
实例讲解JS中数组Array的操作方法
2014/05/09 Javascript
js+css实现导航效果实例
2015/02/10 Javascript
javascript无刷新评论实现方法
2015/05/13 Javascript
jquery弹出遮掩层效果【附实例代码】
2016/04/28 Javascript
require简单实现单页应用程序(SPA)
2016/07/12 Javascript
js代码延迟一定时间后执行一个函数的实例
2017/02/15 Javascript
微信小程序 点击控件后选中其它反选实例详解
2017/02/21 Javascript
angular2+nodejs实现图片上传功能
2017/03/27 NodeJs
移动端web滚动分页的实现方法
2017/05/05 Javascript
vue数组对象排序的实现代码
2018/06/20 Javascript
require.js 加载过程与使用方法介绍
2018/10/30 Javascript
JavaScript canvas实现雪花随机动态飘落
2020/02/08 Javascript
基于vue--key值的特殊用处详解
2020/07/31 Javascript
JS实现简易图片自动轮播
2020/10/16 Javascript
[04:44]DOTA2英雄梦之声_第12期_矮人直升机
2014/06/21 DOTA
[01:27]DOTA2电竞之夜 今夜共饮庆功酒
2014/08/02 DOTA
Python入门篇之文件
2014/10/20 Python
简单解决Python文件中文编码问题
2015/11/22 Python
浅谈Python数据类型判断及列表脚本操作
2016/11/04 Python
python实现视频读取和转化图片
2019/12/10 Python
python 爬取古诗文存入mysql数据库的方法
2020/01/08 Python
分享一枚pycharm激活码适用所有pycharm版本我的pycharm2020.2.3激活成功
2020/11/20 Python
html5 浏览器支持 如何让所有的浏览器都支持HTML5标签样式
2012/12/07 HTML / CSS
实例讲解利用HTML5 Canvas API操作图形旋转的方法
2016/03/22 HTML / CSS
iphoneX 适配客户端H5页面的方法教程
2017/12/08 HTML / CSS
策划助理岗位职责
2013/11/18 职场文书
护理医院见习报告
2014/11/03 职场文书
2015年世界粮食日演讲稿
2015/03/20 职场文书
2015年出纳年终工作总结
2015/05/14 职场文书
航班延误投诉信
2015/07/02 职场文书
员工聘用合同范本
2015/09/21 职场文书
公司年会晚会开幕词
2019/04/02 职场文书