对象是JavaScript基本数据类型。可以看做是属性的一种无序集合。
1.创建对象
对象直接量
创建对象的最简单的方式就是在JavaScript代码中使用对象直接量。
一些例子:
var empty={}; var point={x:0,y:0}; var point2={x:point.x,y:point.y+1}; var book={ "mian-title":"JavaScript", "sub-title":"The Definitive Guide", "for":"all audiences", author: { firstname:"David", lastname:"Flanagan" } }
通过new创建对象
new运算符创建并初始化一个新对象。
var o=new Object(); var a=new Array(); var d=new Date(); var r=new RegExp("js");
原型
每一个JavaScript对象(除null外)都与另一个对象相关联,“另一个”对象就是我们熟知的原型,每一个对象都重原型继承属性。
通过对象直接量创建的对象都具有同一个原型对象,通过Object.prototype获取对原型对象的引用。通过new Object()创建的对象继承自Object.prototype;通过new Array()创建的对象的原型就是Array.prototype.
没有原型的对象不多,Object.prototype就是其中之一。
Object.create()创建对象
Object.create()是一个静态函数,它创建一个新对象,第一个参数是这个对象的原型,第二个参数时可选的,用于对该对象的描述
var o1=Object。create({x:1,y:2}); //o1继承了属性x和y 如果参数为null,不继承任何东西,把偶奇偶toString()等 创建一个普通的空对象,可以这样: var o2=Object.create(Object.prototype);
2.属性的查询和设置
可以通过.或者方括号[]运算来得到属性的值
继承
JavaScript对象具有"自有属性“,也有一些属性是从原型对象继承而来的。
如果要查询对象o的属性x,如果o中不存在,则往他的原型中查找,知道找到x或者找到一个原型是null的队形为止。
JavaScript继承使用inherit()函数
var o={}; o.x=1; var p=inherit(o); //对象p继承对象o p.y=2; var q=inherit(p); q.z=3; var s=q.toString(); q.x+q.y
访问属性错误
查询一个不存在的属性不会报错,没有找到返回undefined
但是,查询不存在的对象的属性会报错。
var len=book.subtitle.length; //不存在book,undefined没有length属性 除非确定对应对象存在否则不能上面这样写 优化: var lerr=undefined; if(book){ if(book.subtitle){ len=book.subtitle.length; } } var len=book&&book.subtitle&& book.subtitle.length;
删除属性
delete运算符的使用
this.x=1;
delete x;
检测属性
通过in运算符、hasOwnPreperty()、和propertyIsEnumerable()完成
in运算符的左侧是属性名(字符串),右侧是对象。如果对象的自由属性或者继承属性中包含这个属性则返回true
var o={x:1}; "x" in o; ==>true "y" in o; ==>false "toString" in o==>true
hasOwnProperty()检测给定的名字是否是对象的自由属性。对于继承属性它返回false
var o={x:1}; o.hasOwnProperty("x"); ==>true o.hasOwnProperty("y"); ==>false o.hasOwnProperty("toString"); ==>false
peopertyIsEnumerable()是hasOwnProperty()的增强版,只有检测到自由属性,且这个属性的可枚举型为true才返回true
枚举属性
遍历对象的属性,通常使用for/in循环
for/in循环可以遍历对象中所有可枚举属性
Object.keys()返回一个由对象中可枚举的自有属性名称组成的数组
Object.getOwnPropertyNames()返回对象的所有自有属性的名称属性的geteter、setter
对象属性是由名字、值和一组特征构成的。在ECMAScript5中,属性值可以用一个或两个方法替代。这两个方法就是getter和setter。由getter和setter定义的属性称为”存取器属性“。
当程序查询存取属性的值的时候,JavaScript调用getter方法(无参数)。这个方法的返回值就是属性存取表达式的值。JavaScript调用setter方法,将赋值表达式右侧的值当作参数传入setter。
存取器属性具有不可写性。如果属性同时具有getter和setter方法,那么它是一个读写属性。如果只有getter方法,只读属性。如果只有setter方法,是一个只写属性,读取只写属性会反悔undefined。
var o={ data_prop:value, get accessor_prop(){....}, set accessor_prop(value){...} };
console.log(o.accessor_prop); 存取器属性定义为一个或两个和属性同名的函数,这个函数定义没有使用function关键字,而是使用get和(或)set方法。
对象的继承会继承到存取器属性
7.对象的三个属性
原型属性
前面介绍了新建对象一般是使用的对象的原型属性
检测一个对象是否是另一个对象的原型(或处于原型链中),使用isPeototypeOf()方法
var p={x:1}; var o=Object.create(p); p.isPrototypeOf(o); ==>true Object.prototype.isPrototypeOf(o);==>true
类属性
对象的类属性是一个字符串,用以表示对象的类型信息。
查询对象的类属性要使用默认的toString()方法
function classof(o){ if(o==null) return "Null"; if(o==undefined) return "Undefined"; return Object.property.toString.call(o).slice(8,-1); //这里为了调用正确的toString()版本,必须简介地调用Function.call()方法。 }
实际上是这些类型的变量调用toString()方法,而不是通过它们的直接量调用toString()。比如1.toSring()是不对的,而是要先声明变量 var a=1;然后调用a.toString()。
可拓展性
对象的可拓展性用以表示是否可以给对象添加新属性。所有内置对象和自定义对象都是可拓展的,宿主对象的可拓展性是由JavaScript引擎定义的。
Object.esExtensible(obj)判断该对象obj是否是可拓展的。
Object.preventExtensions(obj)将对象转换成不可拓展的
Object.seal(obj)除了能将对象设置为不可拓展的,还可以将对象的所有自有属性都设置为不可配置的。对于那些已经封闭(sealed)起来的对象是不能解封的。可以使用Object.isSealed()来检测对象是否封闭
Object.freeze()将冻结对象。除了将对象设置称为不可拓展的和将其属性配置为不可配置的外,还将所有的数据属性设置为只读的(如果对象存取器属性具有setter方法,存取器属性不受影响)。Object.isFrozen()来检测对象是否被冻结
8.序列化对象
对象序列化(serialization)是指将对象的状态转换为字符串,也可将字符串还原为对象。
ECMAScript5提供了内置函数JSON.stringify()和JSON.parse()来序列化和还原JavaScript对象。这些方法都是用JSON作为数据交换格式,JSON的全称是JavaScript Object Notation(JavaScript对象表示法,它的语法和JavaScript对象与数组直接量的语法非常相似)
o={x:1,y:{z:[false,null,""]}}; s=JSON.stringify(o); //s是'{"x":1,"y":{"z":[false,null,""]}}}' p=JSON.parse(s); //p是c的深拷贝
9.对象方法
toString()方法:返回一个表示调用这个方法的对象值的字符串。
var s={x:1,y:1}.toString(); ==>[object Object]
toLocaleString()方法
返回这个对象的本地化字符串。Object中默认的toLocalString()方法并不做任何本地化自身的操作,它仅调用toString()方法并返回对应值。
Date和Number类对toLocaleString()做了定责,可以用它对数字、日期和时间做本地化的转换。Array类中的这个方法和toString()方法很像,唯一不同的是每个数组元素会调用toLocaleString()方法转换为字符串,而不是调用各自的toString()方法
toJSON()方法
返回的是序列化的结果Object。property实际上没有定义,单数对于需要执行序列化的对象来说,JSON.stringify()方法会调用同JSON方法。如果在待序列化的对象中存在这个方法,则调用它,返回值即是序列化的结果。
valueOf()方法
valueOf()方法和toString()非常相似。但往往JavaScript需要将对象转换为某种原始值而非字符串的时候才会调用它,尤其是转换为数字的时候。
Integer.valueOf("1");