JavaScript高级程序设计(第3版)学习笔记6 初识js对象


Posted in Javascript onOctober 11, 2012

在房子里面可以放你想放的任意事物——如果你有足够的美学造诣,你甚至可以弄一个房中房试试——当然,为了方便管理,我们会给房子里存放的所有事物都会取上一个不重复的名字,比如医药房间里的各种药品名称。在ECMAScript中,你可以在对象中存放任意你想放的数据,同样,我们需要给存放的数据取一个名字——也就是对象的属性名,再存放各种数据。再看看ECMA-262中对象的定义:无序属性的集合,其属性可以包含简单数据类型值、对象或者函数。

进入对象,我开始有些激动了,说实话,让我想起做这系列学习笔记的最初原因,就是因为该书对对象的深刻论述,让我对JavaScript的认知从客户端验证小工具转变成一门强大的面向对象脚本语言,但我现在也有点犯难了,因为关于对象,有太多太多的东西需要去细化,一时也不知该从哪个点切入,比如要想深入理解对象,作用域、执行环境、闭包这些概念是肯定离不开的,但如果连对象的概念都没说就开始执行环境和闭包,又感觉像是空中楼阁。不过又一想,也就释然了,这毕竟只是自己的个人学习笔记,又不是什么教科书,我大可以使用自己喜欢的方式来做自己的笔记(事实上,在前面的篇章中,我就有意识的重复那些我认为有意思的地方,这就是我喜欢的一种方式),当然,我还是会尽量以一种易于理解的方式来做这些笔记。

对象类型

和5种简单数据类型(Undefined、Null、Boolean、Number、String)相对应,对象(Object)也是一种数据类型,只是这种数据类型比较特别,它不但可以像简单数据类型一样存取通常的数据,而且可以将动作行为作为一种特殊的数据加以存取。

1、对象实例

每种数据类型都有相应的值,比如Undefined类型只有一个值undefined,而数字5是Number类型的一个值。对于对象类型,我们把值称为对象实例,那么对象类型都可以有哪些(值)实例呢?任意一个对象都是对象类型的值(实例),比如简单类型包装对象(Boolean、Number、String)就是对象类型的值(实例)。

2、对象字面量

既然任意一个对象都是对象类型的实例,那么对象实例怎么表示呢?或者说我们在交流过程中怎么书写出对象实例呢?简单数据类型的值很好表示,比如用符号“5”表示数字5,符号“true”表示Boolean值true,这些被称为字面量,那么,有没有对象字面量呢?答案是肯定的,对象字面量就是通过一对大括号({})来表示的。比如:

{ 
name:'linjisong', 
getName:function(){ 
return this.name; 
} 
}

这里最外层的一对大括号({})就表示这是一个对象字面量。另外,还有数组字面量的概念,在ECMAScript中,数组Array是一个继承了Object的对象实例,通过这个对象实例可以创建数组类型的实例,数组类型的实例也可以直接通过数组字面量来表示,方法如下:
[{ 
name:'linjisong', 
age:29 
},{ 
name:'oulinhai', 
age:23 
}]

这里一对中括号([])用于表示数组,这是一个包含了两个对象的数组。通过对象字面量和数组字面量,形成了难以想象的强大表现力,事实上,流行的JSON数据格式就是基于此。

3、创建对象实例

熟悉一般面向对象的朋友都知道,要创建一个类的实例,首先要定义这个类,然后用new关键字来创建这个类的实例(别和我说还可以使用反射,我的Java可学的不好……)。但是在ECMAScript中,根本没有类的概念,那么,对象实例要怎么创建呢?

在ECMAScript中尽管没有类,但是也有某种程度上类似的概念,承担这个角色的就是函数,可以通过new操作符和函数来创建对象实例——每一个对象实例都有一个用于创建这个实例的函数。最基本的函数就是Object(),它是用来创建最一般对象的函数,其它的诸如Number()函数,可以用来创建Number对象的实例,Boolean()函数,可以用来创建Boolean对象的实例:

var obj = new Object();//Object()函数,创建最一般的对象实例 
var num = new Number(1);//Number()函数,创建Number对象的实例 
var boo = new Boolean(true);//Boolean()函数,创建Boolean对象的实例 
console.info(typeof num);//object 
console.info(typeof Number(1));//number 
console.info(typeof boo);//object 
console.info(typeof Boolean(true));//boolean

(1)可以看到,要创建一个对象实例,首先需要有一个函数(称为构造函数),这个函数使用new调用时就是创建对象实例,不使用new时只是通常意义上的函数调用(如果这个函数在内部返回实例了,函数调用也可以创建对象)。

(2)所谓的内置对象实际上也就是内置了一些创建对象实例的函数而已,不同的函数创建不同的内置对象。

(3)关于要不要使用new操作符,我的建议是使用,如果不使用new操作符,有些情况下结果会出乎你的意料之外,像上例中的第5、7行,实际上并没有创建对象,而只是普通的函数调用,这个调用的作用就是转换数据类型。

(4)使用new创建对象实例时,如果调用构造函数不需要传入参数,也可以省略后面的函数调用操作符(()),当然,这种特性也不是什么值得宣扬的事情。

(5)如果需要创建自定义对象的实例,那么首先也需要定义一个构造函数,然后使用new操作符调用创建实例。这里需要注意,如果忘了new的话,可能会污染全局环境:

function Person(){//首先定义一个用于创建对象实例的(构造)函数 
this.name = 'linjisong'; 
this.age = 29; 
} var person = new Person();//调用(构造)函数创建对象实例 
console.info(person.age);//29 
try{ 
console.info(age);//为了演示忘记使用new的情况,这里先输出全局的age,由于未定义,抛出异常 
}catch(e){ 
console.info(e);//ReferenceError 
} 
var person2 = Person();//忘记使用new的情况下,只是普通的函数调用,由于函数没有返回,这里person2就是undefined了 
console.info(person2);//undefined 
console.info(age);//29,没有使用new,内部的this指向了全局作用域,因为可以在全局访问age了

要避免这种问题,可以修改一下构造函数:
function Person(){ 
if(this instanceof Person) 
{ 
this.name = 'linjisong'; 
this.age = 29; 
}else{ 
return new Person(); 
} 
} 
var person2 = Person(); 
console.info(person2.age);//29,可以访问person2的age了 
console.info(age);//全局环境中没有age的定义了,抛出异常

这个构造函数首先判断this值是否为Person类型,如果不是,就在内部使用new调用,以确保返回的值一定是Person类型实例。这种方式使得重构构造函数成为了可能,也许Boolean()、Number()、String()在实现上就是使用了这种方式来区分是构造函数还是转换函数。如果你在调用Object()时省略new的话,结果也能返回对象,估计也是在后台做了类似处理,同样的情况还有本文后部分要讲的函数类型构造函数Function()。

(5)可能有人会问,既然有对象字面量,何必要用这么复杂的方式来创建对象实例呢,直接写对象字面量不就完了?用对象字面量创建对象实例,根本没有使用什么函数,看来,上面的“每一个对象实例都有一个用于创建这个实例的函数”的说法并不正确。

首先第一个问题,的确,可以使用对象字面量来创建函数,而且也非常简洁,这甚至也是我首先推荐的一种创建方式,但是用这种方式创建对象实例,只能创建单例的实例,对于需要创建多个相同类型的对象实例来说并不适用,然后第二个问题,用对象字面量创建对象,实际上并不是没有相应的构造函数,只是构造函数为Object(),使用对象字面量,后台可能不会去调用new Object(),但创建出的对象仍然有指向这个函数的属性,这可以从下面代码输出中得到验证:

var person = {}; 
console.info(person.constructor===Object);//true

这里的constructor是每个实例对象都有的一个属性,用于保存创建这个对象实例的函数,这就是下面要讲的。

4、对象属性和方法

每一种数据类型都有各自的共性,比如Number类型值都有可以和另外一个Number类型值相加的特性,同样,对象类型的实例也有一些相同的特性,这些特性就体现在它们都包含下面的属性和方法(方法实际上也是一种属性,只是属性的值类型是函数的话,我们也称之为方法):

类别 属性/方法 说明
属性 constructor 指向用于创建当前对象的函数
方法 hasOwnProperty(propertyName) 检查给定的属性是否在当前对象实例中
propertyIsEnumerable(propertyName) 检查给定的属性是否能够是使用for-in语句来枚举
isPrototype(object) 检查传入的对象是否是另一个对象的原型
toLocalString() 返回对象的字符串表示,该字符串与执行环境的地区相对应
toString() 返回对象的字符串表示
valueOf() 返回对象的字符串、数值或布尔值表示,通常与toString()方法返回值相同

注:在《JavaScript高级程序设计(第3版)》第35页中的Constructor将首字母大写了,应该是一个印刷错误。

属性和方法的访问有两种方式:

(1)使用点号(.):如person.name。

(2)使用方括号([]):如person[name],使用这种方式,方括号内部可以是一个变量或者表达式,这使得可以访问名称包含特殊符号的属性和方法。

通过结合for-in和这里的hasOwnProperty (propertyName),我们就可以遍历对象实例自身的属性而不包括从原型链继承而来的属性了:

for(var propertyName in object){ 
if(object.hasOwnPorperty(propertyName)){ 


//循环处理 

} 
}
Javascript 相关文章推荐
javascript 字符 Escape,encodeURI,encodeURIComponent
Jul 09 Javascript
前台js改变Session的值(用ajax实现)
Dec 28 Javascript
JSONP跨域的原理解析及其实现介绍
Mar 22 Javascript
三种取消选中单选框radio的方法
Sep 09 Javascript
JS烟花背景效果实现方法
Mar 03 Javascript
jQuery+css3实现转动的正方形效果(附demo源码下载)
Jan 27 Javascript
JavaScript中两个字符串的匹配
Jun 08 Javascript
Angular工具方法学习
Dec 26 Javascript
Angularjs通过指令监听ng-repeat渲染完成后执行脚本的方法
Dec 31 Javascript
简单了解JavaScript中的执行上下文和堆栈
Jun 24 Javascript
JQuery+drag.js上传图片并且实现图片拖曳
Nov 18 jQuery
在vue中动态修改css其中一个属性值操作
Dec 07 Vue.js
JavaScript高级程序设计(第3版)学习笔记5 js语句
Oct 11 #Javascript
JavaScript高级程序设计(第3版)学习笔记4 js运算符和操作符
Oct 11 #Javascript
JavaScript高级程序设计(第3版)学习笔记3 js简单数据类型
Oct 11 #Javascript
JavaScript高级程序设计(第3版)学习笔记2 js基础语法
Oct 11 #Javascript
JavaScript高级程序设计(第3版)学习笔记 概述
Oct 11 #Javascript
javascript测试题练习代码
Oct 10 #Javascript
jQuery插件开发全解析
Oct 10 #Javascript
You might like
PHP音乐采集(部分代码)
2007/02/14 PHP
jquery无法设置checkbox选中即没有变成选中状态
2014/03/27 Javascript
yepnope.js使用详解及示例分享
2014/06/23 Javascript
node.js中使用socket.io制作命名空间
2014/12/15 Javascript
JavaScript组件开发完整示例
2015/12/15 Javascript
javascript对象的相关操作小结
2016/05/16 Javascript
js实现简单的获取验证码按钮效果
2017/03/03 Javascript
利用JS制作万年历的方法
2017/08/16 Javascript
跨域请求两种方法 jsonp和cors的实现
2018/11/11 Javascript
使用 Opentype.js 生成字体子集的实例代码详解
2020/05/25 Javascript
[04:14]从西雅图到上海——玩家自制DOTA2主题歌曲应援TI9
2019/07/11 DOTA
python使用super()出现错误解决办法
2017/08/14 Python
使用实现pandas读取csv文件指定的前几行
2018/04/20 Python
基于pandas数据样本行列选取的方法
2018/04/20 Python
Python实现输入二叉树的先序和中序遍历,再输出后序遍历操作示例
2018/07/27 Python
Python在图片中插入大量文字并且自动换行
2019/01/02 Python
Python通过fnmatch模块实现文件名匹配
2020/09/30 Python
浅析Python requests 模块
2020/10/09 Python
水果花束:Fruit Bouquets
2017/12/20 全球购物
美国学校用品、教室和教学商店:Discount School Supply
2018/04/04 全球购物
银行毕业实习自我鉴定
2013/09/19 职场文书
咨询公司各岗位职责
2013/12/02 职场文书
安全检查管理制度
2014/02/02 职场文书
经贸日语专业个人求职信范文
2014/04/29 职场文书
法制宣传月活动方案
2014/05/11 职场文书
员工合理化建议书
2014/05/19 职场文书
大专生自我鉴定怎么写
2014/09/16 职场文书
党员教师四风问题对照检查材料
2014/09/26 职场文书
异地恋情人节寄语
2015/02/28 职场文书
国家助学贷款承诺书
2015/04/30 职场文书
《神奇的鸟岛》教学反思
2016/02/22 职场文书
深入理解CSS 中 transform matrix矩阵变换问题
2021/08/30 HTML / CSS
如何利用Python实现n*n螺旋矩阵
2022/01/18 Python
【海涛dota】偶遇拉娜娅 质量局德鲁伊第一视角解说
2022/04/01 DOTA
Win11自动黑屏怎么办 Win11自动黑屏设置教程
2022/07/15 数码科技
CSS 鼠标选中文字后改变背景色的实现代码
2023/05/21 HTML / CSS