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 相关文章推荐
CutePsWheel javascript libary 控制输入文本框为可使用滚轮控制的js库
Feb 07 Javascript
jQuery滚动加载图片效果的实现
Mar 06 Javascript
jquery获取复选框被选中的值
Apr 10 Javascript
jQuery使用之处理页面元素用法实例
Jan 19 Javascript
JS动态改变浏览器标题的方法
Apr 06 Javascript
基于jQuery实现选项卡效果
Jan 04 Javascript
实例详解display:none与visible:hidden的区别
Mar 30 Javascript
详解Vue2中组件间通信的解决全方案
Jul 28 Javascript
Three.js中矩阵和向量的使用教程
Mar 19 Javascript
Angular4.0动画操作实例详解
May 10 Javascript
vue-cli3添加模式配置多环境变量的方法
Jun 05 Javascript
nuxt 路由、过渡特效、中间件的实现代码
Nov 06 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
php unicode编码和字符串互转的方法
2020/08/12 PHP
PHP jQuery+Ajax结合写批量删除功能
2017/05/19 PHP
PHP设计模式概论【概念、分类、原则等】
2020/05/01 PHP
ASP中用Join和Array,可以加快字符连接速度的代码
2007/08/22 Javascript
将函数的实际参数转换成数组的方法
2010/01/25 Javascript
JS中prototype关键字的功能介绍及使用示例
2013/07/21 Javascript
Jquery each方法跳出循环,并获取返回值(实例讲解)
2013/12/12 Javascript
JavaScript中奇葩的假值示例应用
2014/03/11 Javascript
JS实现静止元素自动移动示例
2014/04/14 Javascript
jQuery中size()方法用法实例
2014/12/27 Javascript
JS实现的简洁纵向滑动菜单(滑动门)效果
2015/10/19 Javascript
fastclick插件导致日期(input[type="date"])控件无法被触发该如何解决
2015/11/09 Javascript
JavaScript日期选择功能示例
2017/01/16 Javascript
解决AjaxFileupload 上传时会出现连接重置的问题
2017/07/07 Javascript
浅谈用Webpack路径压缩图片上传尺寸获取的问题
2018/02/22 Javascript
JavaScript中为事件指定处理程序的五种方式分析
2018/07/27 Javascript
VUE 组件转换为微信小程序组件的方法
2019/11/06 Javascript
JavaScript 双向链表操作实例分析【创建、增加、查找、删除等】
2020/04/28 Javascript
element-ui中dialog弹窗关闭按钮失效的解决
2020/09/22 Javascript
Python自动化开发学习之三级菜单制作
2017/07/14 Python
python爬虫_自动获取seebug的poc实例
2017/08/05 Python
OpenCV图像颜色反转算法详解
2019/05/13 Python
Pandas之ReIndex重新索引的实现
2019/06/25 Python
一文秒懂python读写csv xml json文件各种骚操作
2019/07/04 Python
CSS3 text-shadow实现文字阴影效果
2016/02/24 HTML / CSS
Radley英国官网:英国莱德利小狗包
2019/03/21 全球购物
港湾网络笔试题
2014/04/19 面试题
幼儿教师工作感言
2014/02/14 职场文书
幼儿园教研活动总结
2014/04/30 职场文书
询价采购方案
2014/06/09 职场文书
村干部群众路线教育活动对照检查材料
2014/10/01 职场文书
婚前协议书标准版
2014/10/19 职场文书
2014年办公室工作总结范文
2014/11/12 职场文书
2015年母亲节活动总结
2015/02/10 职场文书
节水宣传标语口号
2015/12/26 职场文书
将图片保存到mysql数据库并展示在前端页面的实现代码
2021/05/02 MySQL