您好,欢迎访问三七文档
第6章对象本章目标了解什么是对象什么时候定义对象如何定义对象使用Object的注意事项对象是JavaScript的基本数据类型。在了解JavaScript对象之前,我们先浅显了解什么是对象。对象就是事物,只是因为计算机编程语言是外国人发明的,起名为object。对于中国人来说称之为事物,物体更好理解。在计算机的世界中万物皆为对象,人,动物,计算器,窗口,按钮,英雄联盟中的人物,飞机大战中的子弹等。对象是一种复合值:它将很多值(原始值或者其他对象)聚合在一起,可通过名字访问这些值。对象也可看作是属性的无序集合,每个属性都是一个名/值对。属性名是字符串,因此我们可以把对象看成是从字符串到值的映射。然而对象不仅仅是字符串到值的映射,除了可以保持自有的属性,JavaScript对象还可以从一个称为原型的对象继承属性。对象的方法通常是继承的属性。这种“原型式继承”(prototypalin-heritance)是JavaScript的核心特征。JavaScript对象是动态的可以新增属性也可以删除属性,但它们常用来模拟静态对象以及静态类型语言中的“结构体”(struct)。有时它们也用做字符串的集合(忽略名/值对中的值)。除了字符串、数字、true、false、null和undefined之外,JavaScript中的值都是对象。尽管字符串、数字和布尔值不是对象,但它们的行为和不可变对象非常类似。对象是可变的,我们通过引用而非值来操作对象。如果变量x是指向一个对象的引用,那么执行代码vary=x;变量y也是指向同一个对象的引用,但不是这个对象的副本。通过变量y修改这个对象亦会对变量x造成影响。对象最常见的用法是创建(create)、设置(set)、查找(query)、删除(delete)、检测(test)和枚举(enumerate)它的属性。我们会在开始的几节讲述这些基础操作。后续的几节讲述高级主题,其中相当一部分内容来自于EC-MAScript5。刚才我们通过浅显的语文说明了什么是对象,也有专业的术语描述了对象。现在我们了解什么是属性?对象是由多个属性够成,属性可以是任意数据类型。例如人的属性有身高,肤色,体重;动物的属性有是否是哺乳动物,几只腿。JavaScript中属性包括名字和值。属性名可以是包含空字符串在内的任意字符串,但对象中不能存在两个同名的属性。值可以是任意JavaScript值。6.1创建对象可以通过对象直接量、关键字new和(EC-MAScript5中的)Object.create()函数来创建对象。接下来几节将对这些技术一一讲述。6.1.1对象直接量创建对象最简单的方式就是在JavaScript代码中使用对象直接量。对象直接量是由若干名/值对组成的映射表,名/值对中间用冒号分隔,名/值对之间用逗号分隔,整个映射表用花括号括起来。属性名可以是JavaScript标识符也可以是字符串直接量(包括空字符串)。属性的值可以是任意类型的JavaScript表达式,表达式的值(可以是原始值也可以是对象值)就是这个属性的值。下面有一些例子:varempty={};//没有任何属性的对象varpoint={x:0,y:0};//两个属性varpoint2={x:point.x,y:point.y+1};//varbook={maintitle:JavaScript,//属性名字里有空格,必须用字符串表示'sub-title':TheDefinitiveGuide,//属性名字里有连字符,必须用字符串表示for:allaudiences,//for是保留字,因此必须用引号author:{//这个属性的值是一个对象firstname:David,//注意,这里的属性名都没有引号surname:Flanagan}};在ECMAScript5(以及ECMAScript3的一些实现)中,保留字可以用做不带引号的属性名。然而对于ECMAScript3来说,使用保留字作为属性名必须使用引号引起来。在ECMAScript5中,对象直接量中的最后一个属性后的逗号将忽略,且在ECMAScript3的大部分实现中也可以忽略这个逗号,但在IE中则报错。对象直接量是一个表达式,这个表达式的每次运算都创建并初始化一个新的对象。每次计算对象直接量的时候,也都会计算它的每个属性的值。也就是说,如果在一个重复调用的函数中的循环体内使用了对象直接量,它将创建很多新对象,并且每次创建的对象的属性值也有可能不同。6.1.2通过new创建对象new运算符创建并初始化一个新对象。关键字new后跟随一个函数调用。这里的函数称做构造函数(constructor),构造函数用以初始化一个新创建的对象。JavaScript语言核心中的原始类型都包含内置构造函数。例如:varo=newObject();//创建一个空对象,和{}一样vara=newArray();//创建一个空数组,和[]一样vard=newDate();//创建一个表示当前时间的Date对象varr=newRegExp(js);//创建一个可以进行模式匹配的EegExp对象除了这些内置构造函数,用自定义构造函数来初始化新对象也是非常常见的。第9章将详细讲述其中的细节。6.1.3原型在讲述第三种对象创建技术之前,我们应当首先解释一下原型。原型是JS区别其它编程语言的最重要的特征。每一个JavaScript对象(null除外)都和另一个对象相关联。“另一个”对象就是我们熟知的原型,每一个对象都从原型继承属性。所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过JavaScript代码Object.prototype获得对原型对象的引用。通过关键字new和构造函数调用创建的对象的原型就是构造函数的prototype属性的值。因此,同使用{}创建对象一样,通过newObject()创建的对象也继承自Object.prototype。同样,通过newArray()创建的对象的原型就是Array.prototype,通过newDate()创建的对象的原型就是Date.prototype。没有原型的对象为数不多,Object.prototype就是其中之一。它不继承任何属性。其他原型对象都是普通对象,普通对象都具有原型。所有的内置构造函数(以及大部分自定义的构造函数)都具有一个继承自Object.prototype的原型。例如,Date.prototype的属性继承自Object.prototype,因此由newDate()创建的Date对象的属性同时继承自Date.prototype和Object.prototype。这一系列链接的原型对象就是所谓的“原型链”(prototypechain)。而这一高级部分我们会在JS高级课程里面讲解6.1.4Object.create()ECMAScript5定义了一个名为Object.cre-ate()的方法,它创建一个新对象,其中第一个参数是这个对象的原型。Object.create()提供第二个可选参数,用以对对象的属性进行进一步描述。6.7节会详细讲述第二个参数。Object.create()是一个静态函数,而不是提供给某个对象调用的方法。使用它的方法很简单,只须传入所需的原型对象即可:varo1=Object.create({x:1,y:2});//o1继承了属性x和y可以通过传入参数null来创建一个没有原型的新对象,但通过这种方式创建的对象不会继承任何东西,甚至不包括基础方法,比如toString(),也就是说,它将不能和“+”运算符一起正常工作:varo2=Object.create(null);//o2不继承任何如果想创建一个普通的空对象(比如通过{}或newObject()创建的对象),需要传入Object.prototype:varo3=Object.create(Object.prototype);//o3和{}和newObject()一样varo2={};varo1=newObject();可以通过任意原型创建新对象(换句话说,可以使任意对象可继承),这是一个强大的特性。在ECMAScript3中可以用类似例6-1中的代码来模拟原型继承:例6-1:通过原型继承创建一个新对象//inherit()返回了一个继承自原型对象p的属性的新对象//这里使用ECMAScript5中的Object.create()函数(如果存在的话)//如果不存在Object.create(),则退化使用其他方法functioninherit(p){if(p==null)throwTypeError();//p是一个对象,但不能是nullif(Object.create)//如果Object.create()存在returnObject.create(p);//直接使用它vart=typeofp;//否则进行进一步检测if(t!==object&&t!==function)throwTypeError();functionf(){};//定义一个空构造函数f.prototype=p;//将其原型属性设置为preturnnewf();//使用f()创建p的继承对象}在看完关于构造函数的内容后,例6-1中的inherit()函数会更容易理解。现在只要知道它返回的新对象继承了参数对象的属性就可以了。注意,inherit()并不能完全代替Object.create(),它不能通过传入null原型来创建对象,而且不能接收可选的第二个参数。不过我们仍会在本章和第9章的示例代码中多次用到inherit()。inherit()函数的其中一个用途就是防止库函数无意间(非恶意地)修改那些不受你控制的对象。不是将对象直接作为参数传入函数,而是将它的继承对象传入函数。当函数读取继承对象的属性时实际上读取的是继承来的值。如果给继承对象的属性赋值,则这些属性只会影响这个继承对象自身,而不是原始对象:varo={x:don'tchangethisvalue};library_function(inherit(o));//防止对o的意外修改了解其工作原理,需要首先了解JavaScript中属性的查询和设置机制。接下来会讲到。6.2属性的查询和设置4.4节已经提到,可以通过点(.)或方括号([])运算符来获取属性的值。运算符左侧应当是一个表达式,它返回一个对象。对于点(.)来说,右侧必须是一个以属性名称命名的简单标识符。对于方括号来说([]),方括号内必须是一个计算结果为字符串的表达式,这个字符串就是属性的名字:varauthor=book.author;//得到book的author属性varname=author.surname//得到获得author的surname属性vartitle=book[maintitle]//得到book的maintitle属性和查询属性值的写法一样,通过点和方括号也可以创建属性或给属性赋值,但需要将它们放在赋值表达式的左侧:book.edition=6;//给book创建一个名为edition的属性book[maintitle]=ECMAScript;//给maintitle属性赋值在ECMAScript3中,点运算符后的标识符不能是保留字,比如,o.for或o.class是非法的,因为for是JavaScript的关键字,class是保留字。如果一个对象的属性名是保留字,则必须使用方括号的形式访问它们,比如o[for]和o[class]。EC-MAScript5对此放宽了限制(包括ECMAScript3的某些实现),可以在点运算符后直接使用保留字。当使用方括号时,我们说方括号内的表达式必须返回字符串。其实更严格地讲,表达式必须返回字符串或返回一个可以转换为字符串的值。在第7章里有一些例子中的方括号内使用了数字,这情况象是非常常见的。6.2.1作为关联数组的对象上文提到,下面两个JavaScript表达式的值相同:object.propertyobject[prope
本文标题:document
链接地址:https://www.777doc.com/doc-2910190 .html