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 相关文章推荐
基于jquery的一行代码轻松实现拖动效果
Dec 28 Javascript
Jquery.LazyLoad.js修正版下载,实现图片延迟加载插件
Mar 12 Javascript
javascript学习笔记(十九) 节点的操作实现代码
Jun 20 Javascript
Bootstrap3学习笔记(二)之排版
May 20 Javascript
Bootstrap中点击按钮后变灰并显示加载中实例代码
Sep 23 Javascript
AngularJS实现路由实例
Feb 12 Javascript
基于vue实现多引擎搜索及关键字提示
Mar 16 Javascript
基于 Vue 的树形选择组件的示例代码
Aug 18 Javascript
jQuery.extend 与 jQuery.fn.extend的用法及区别实例分析
Jul 25 jQuery
对angularJs中$sce服务安全显示html文本的实例
Sep 30 Javascript
js字符串处理之绝妙的代码
Apr 05 Javascript
jQuery 淡入/淡出效果函数用法分析
May 19 jQuery
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
PHP常见加密函数用法示例【crypt与md5】
2019/01/27 PHP
PHP 数组黑名单/白名单实例代码详解
2019/06/04 PHP
一个JS的日期格式化算法示例
2013/07/31 Javascript
javascript原生和jquery库实现iframe自适应高度和宽度
2014/07/18 Javascript
jquery常用操作小结
2014/07/21 Javascript
JavaScript实现N皇后问题算法谜题解答
2014/12/29 Javascript
JS动态修改iframe内嵌网页地址的方法
2015/04/01 Javascript
利用jquery实现下拉框的禁用与启用
2016/12/07 Javascript
jQuery中clone()函数实现表单中增加和减少输入项
2017/05/13 jQuery
详解在vue-cli中使用graphql即vue-apollo的用法
2018/09/08 Javascript
微信小程序swiper实现文字纵向轮播提示效果
2020/01/21 Javascript
JavaScript中EventBus实现对象之间通信
2020/10/18 Javascript
使用python绘制人人网好友关系图示例
2014/04/01 Python
跟老齐学Python之再深点,更懂list
2014/09/20 Python
python中函数总结之装饰器闭包详解
2016/06/12 Python
fastcgi文件读取漏洞之python扫描脚本
2017/04/23 Python
Python向Excel中插入图片的简单实现方法
2018/04/24 Python
Python实现计算长方形面积(带参数函数demo)
2020/01/18 Python
Python任务调度利器之APScheduler详解
2020/04/02 Python
利用python3筛选excel中特定的行(行值满足某个条件/行值属于某个集合)
2020/09/04 Python
css3.0 图形构成实例练习一
2013/03/19 HTML / CSS
美国第一个网上卖鞋零售商:OnlineShoes.com
2017/09/24 全球购物
澳大利亚购买太阳镜和眼镜网站:Glamoureyes
2020/09/22 全球购物
银行职员思想汇报
2013/12/31 职场文书
质量承诺书范文
2014/03/27 职场文书
食品流通安全承诺书
2014/05/22 职场文书
群众路线教育实践活动思想汇报(2014特荐篇)
2014/09/16 职场文书
2014年教师党员自我评价范文
2014/09/22 职场文书
中学生检讨书范文
2014/11/03 职场文书
2014年组织委员工作总结
2014/12/01 职场文书
个人汇报材料范文
2014/12/30 职场文书
2015年安全生产目标责任书
2015/01/29 职场文书
2015年妇产科工作总结
2015/05/18 职场文书
超市店长竞聘书
2015/09/15 职场文书
《好妈妈胜过好老师》:每个孩子的优秀都是有源头的
2020/01/03 职场文书
vue递归实现树形组件
2022/07/15 Vue.js