一、对象概述
对象是javascript的基本数据类型。对象是一种复合值:它将很多值聚合在一起,可以通过名字访问这些值。对象也可看做是属性的无序集合,每个属性都是一个名/值对。属性名是字符串,因此我们可以把对象看成是从字符串到值的映射。然而对象不仅仅是字符串到值的映射,除了可以保持自有的属性,javascript对象还可以从一个称为原型的对象继承属性。对象的方法通常是继承的属性。这种“原型式继承”是javascript的核心特征。对象最常见的用法是创建、设置、查找、删除、检测、枚举它的属性。当然除了名字和值之外,每个属性还有一些与之相关的值 ,称为“属性特性”:
1、 可写,表明是否可以设置该属性的值。
2、可枚举,表明是否可以通过for/ini循环返回该属性。
3、可配置,表明是否可以删除或修改该属性。
除了包含属性之外,每个对象还拥有三个相关的对象特性:
1、对象的原型指向另外一个对象,本对象的必发继承自它的原型对象。
2、对象的类是一个标识对象的字符串。
3、 对象的扩展标记指明了是否可以向该对象添加新属性。
最后,需要指出的是的javascript中对象可以分为三类,其属性可以分为两类:
1、内置对象是由ECMAScript规范定义的对象或类。例如,数组、函数、日期和正则表达式都是内置对象。
2、宿主对象是由JavaScript解释器所嵌入的宿主环境(如Web浏览器)定义的。客户端 Javascipt中表示网页结构的HTMLElement对象均是宿主对象。
3、自定义对象是由运行中的Javascript代码创建的对象
4、自有属性是直接在对象中定义的属性
5、继承属性是在对象的原型对象中定义的属性。
二,对象的创建方法
2.1 对象直接量
创建对象最简单的方式就是在 Javascript代码中使用对象直接量。对象直接量是由若干名/值对组成的映射表,名/值对中间用冒号分隔,名/值对之间用逗号分隔,整个映射表用花括号括起来。属性名可以是JavaScript标识符也可以是字符串直接量。属性的值可以是任意类型的JavaScript表达式,表达式的值(可以是原始值也可以是对象值)就是这个属性的值,例如:
var empty={}; //没有任何属性的对象
var point={x:0,y:0} //两个属性
var point2={x:point.x,y:point.y+1};//更复杂的值
var book={
"main title":"JavaScript", //属性名字里有空格,必须用字符串表示
"sub-title":"The definitive Guide",//属性名字里有连字符,必须用字符串表示
"for":"all audiences", //“for”是保留字,因此必须用引号
author:{ //这个属性的值是一个对象
firstname:"David", //这里的属性名都没有引号
surname:"Flanagan"
}
};
对象直接量是一个表达式,这个表达式的每次运算都创建并初始化一个新的对象。每次计算对象直接量的时候,也都会计算它 的每个属性值。也就是说,如果在一个重复调用的函数中的循环体内使用了对象直接量,它将创建很多新对象,并且每次创建的对象的属性值也有可能不同。
2.2 通过new创建对象
new运算符创建并初始化一个新对象。关键字new后跟随一个函数调用。这里的函数叫做构造函数。构造函数用以初始化一个新创建的对象。JavaScript语言核心中的原始类型都包含内置构造函数。如:
var o=new Object(); //创建一个空对象,和{}一样
var a=new Array(); //创建一个空数组,和[]一样
var d=new Date(); //创建一个表示当前时间Date对象
var r=new RegExp("js") //创建一个可以进行模式匹配的RegExp对象
除了这些内置构造函数,用自定义函数来初始化新对象也是非常常见的。
2.3 原型
所有通过对象直接量创建的对象都具有同一个原型对象,并可以通过JavaScript代码Object.prototype获得对原型对象的引用。通过关键字new和构造函数创建的对象的原型就是构造函数的prototype属性的值。因此,同使用{}创建对象一样,通过new Object()创建的对象也继承自Object.prototype。同样,通过new Array()创建的对象的原型就是Array.prototype,通过new Date()创建的对象的原型就是Date.prototype。
没有原型的对象为数不多,Object。prototype就是其中之一。它不继承任何属性。其他原型对象都是普通对象,普通对象都具有原型。所有的内置构造函数(以及大部分自定义的构造函数)都具有一个继承自Object.prototype,因此由new Date()创建的Date对象的属性同时继承自Date.prototype和Object.prototype。这一系列链接的原型对象就是所谓的“原型链”。
2.4 Object.create()
Object.create()可以创建一个新对象,其中第一个参数就是这个对象的原型。Object.create()提供第二个可选参数,用以对对象的属性进行进一步描述。
这是一个静态函数,而不是提供给某个对象调用的方法。使用它的方法很简单,只须传入所需的原型对象即可:
var o1=Object.create({x:1,y:2}); //o1继承了属性x和y
可以通过传入参数null来创建一个没有原型的新对象,但通过这种方式创建的对象不会继承任何东西,甚至不包括基础方法,比如toString(),也就是说,它将不能和“+”运算符一起正常工作:
var o2=Object.create(null); //o2不继承任何属性和方法
如果想创建一个普通的空对象(比如通过{}或new Object()创建的对象),需要传入Object.prototype:
var o3=Object.create(Object.prototype);//o3和{} 、new Object()一样
可以通过 任意原型创建新对象(换句话说,可以使任意对象可继承),这是一个强大的特性。例如通过原型继承来创建一个新对象。
function inherit(p){ if(!p){throw new TypeError();} if(Object.create){ return Object.create(p); } var t=typeof p; if(t!='object'&&t!='function'){ throw new TypeError(); } function f(){}; f.prototype=p; return new f(); }
三,对象的属性特性
除了包含名字和值之外,属性还包括一些标识它们可写、可枚举和可配置的特性。属性又可以分为自有属性和继承属性。在ECMAScript 3中无法设置这些特性,所有通过ECMAScript 3的程序创建的属性都是可写的、可枚举的和可配置的,且无法对这些特性做修改。但在ES5中提供了查询和设置这些属性特性的API。对于这此属性的设置对库的开发者来说是非常重要,因为:
可以通过这些API给原型对象添加方法,并将它们设置成不可枚举的,这让它们看起来更像内置方法。
可以通过这些API给对象定义不能修改或删除的属性,借此“锁定”这个对象。
数据属性的4个特性分别是它的值、可写性、可枚举性、和可配置性。存取器属性不具有值特性和可写性,它们的可写性是由setter方法存在与否决定的。加些存取器属性的4个特性是读取、写入、可枚举性和可配置性。以下为关于属性特性操作的常用API。
1,Object.defineProperty(),该方法可设置属性的特性,或者想让新建属性具有某种特性,参数依次为要修改的对象、要创建或修改的属性名以及属性描述符对象。
2、如果要同时修改或创建多个属性,则需要使用Object.defineProperties()。第一个参数是要修改的对象,第二个参数是一个映射表,它包括要新建或修改的属性的名称,以及它们的属性描述符。例如:
var p=Object.defineProperties({},{
x:{value:1,writable:true,enumerable:true,configurable:true},
y:{value:1,writable:true,enumerable:true,configurable:true},
r:{
get:function(){return Math.sqrt(this.x*this.x+this.y*this.y)},
enumerable:true,
configurable:true
}
});
3、Object.getOwnPropertyDescriptor() 可以获得某个对象特定属性的属性描述符。参数依次为具体的对象以及该对象的属性。