JavaScript权威指南阅读笔记3
第六章 对象
1.首先是先介绍了对象直接量的格式:对象直接量就是1.由若干个名/值对组成的映射表,2名/值对中间由冒号分割,3名值对之间由逗号分割,4整个映射表由花括号括起来。这样就组成了一个对象直接量了。属性名可是是标识符或者字符串直接量,属性值可以使任意形式的JS表达式,表达式的值就是属性的值。就是平常所接触的对象的形式,比如:
var a= { a:111,b:222}
作者还举了一个需要特别注意的知识的例子:
var b = { "main title" : "aaa", //属性的名字里有空格,所以必须用字符串表示 "sub-title":"bbb", //属性名字有连字符,必须用字符串表示 "for":"ccc",//"for"是系统保留字,所以必须用引号 author:{ firstname:"dava", lastname:"aaa" } }
2. 构建一个新对象的时候可以new一个,
var a = new Object(); var b = new Array(); var c = new Date();
其中Object()、Array()等都是构造函数
3. 另外还可以通过Object.creat()方法新建一个对象,例如:
var d = object.creat(e) //e为D的原型.
关于对象的原型的这个概念跟Java里父类的概念有些相似,具体的介绍可以查看一下下面这篇博文:
原型对象和原型类:
http://www.cnblogs.com/xqhppt/archive/2012/02/01/2334355.html
当以e为原型创建一个对象d的时候,d{c:"ccc"}就继承了e的属性,比如说e为{a:"aaa",b:"bbb"}:d.c叫做d的"自有属性",同时d也会有d.a和d.b这两个属性,只不过这两个属性会显示为继承自原型的属性,但是他们是属于d的属性,当你使用d.a和d.b的时候,js会在d的属性中查找,当js在d中没有找到a和b属性的时候,js就会在它的原型e中查找,在e中找到了a和b之后,js会给对象d创造两个d.a和d.b属性,并对这两个值进行操作,但是不会对原型对象e产生任何影响.
4. 关于访问对象的属性有两种方法,一种是像Java一样通过.进行访问,点的右方必须是一个一属性名称命名的简单标识符如 book.author,book.name等,另一种方法是通过方括号来访问,方括号内必须是一个计算结果为字符串或者计算结果能转换成字符串的表达式,这个字符串也就是属性的名字,比如book["main title"]
object.property与object["property"]意义是一样的.
按照习惯都使用.的方式来操作对象的属性,当我们不知道对象属性的名字的时候,我们通过方括号的方式来操作属性或者获取属性的名字,例如:
for(stock in portfolio){ var shares =protfolio[stock]; }
这样我们就可以通过方括号的方式来便利一个对象里所有属性的值了,即便是我们不知道属性的名字.
5.在访问对象的时候并不总是成功返回值或者设置属性值,比如:当你访问一个对象的并不存在的属性的时候,会得到一个undifined的返回值;当你访问一个并不存在的对象的时候则JS就会报错,作者提供给了我们两端避免访问的错误而导致程序报错的方法:
假设不知道是否存在book和book.title,但是我们想获取book.title的length 则: 1. var leng= undifined if(book){ if(book.title){ leng=book.title.length; } } 2 var leng = book&&book.title&&book.title.length
对null和undifined进行属性赋值,也会包类型错误,
另外还有其他的无法正常赋值的情况:
a.如果o中的p属性是只读的,则不能给p进行赋值
b.如果o中的p属性是继承而来的,但是也只读的,则也不能进行覆盖
c.如果o中不存在属性p,也不存在继承自p的setter,且p是不可拓展的,则不能添加新属性p.
6.可以通过delete删除对象的一个属性,比如:delete book.title,delete book["main title"],但是delete删除的属性和宿主对象的联系(作者在这里举了一个例子来解释这句话:a={p:{x:1}}),b=a.p,delete a.p.这是 b.x的值仍然是1,也就是说delete仅仅珊瑚了a与属性p之间的联系,并没有想象到b跟p的联系)
delete只能删除对象的自由属性,并不能操作继承自原型的属性.如果delete了原型的一个属性,那么也会影响到每一个继承自这个原型的对象.
delete不能删除一个对象的可配置性为flase的属性.
在非严格模式下,删除全局对象的可配置属性的时候可以省略对全局对象的引用,如:
this.x=1;
deleete x;
但是在严格模式下,删除全局对象的可配置属性必须加上对全局对象的引用
this.x =1
delete this.x;
7.JS的对象可以看做是属性的集合.我们需要检测对象是否存在某条属性的时候,可以用in,hasOwnProperty()和 propertyIsEnumerable()方法.
in判断对象是否存在这条属性,比如:
var a ={x:1}
"x" in a; //true
hasOwnProperty()判断属性是否是对象的自有属性,通过集成得到的属性则会返回false
如: o.hasOwnProperty("x")//true o.hasOwnProperty("toString") //false
8.属性具有可枚举性,当属性的可枚举性为true的时候,可以通过for/in循环便利到这个属性,如果可枚举性为flase,怎不可以,如:
var o={x:1,y:2,z:3}; o.propertIsEnumable("toString") //错误,不可枚举 for( i in o){ console.log("i") //输出x/y/z }
ECMAScript 5提供了两个可以获取枚举属性名称的函数:
1:Object.key();他会返回一个由对象的可枚举的自有属性的名称组成的数组
2:Object.getOwnProperty():他返回的是一个有对象所有自有属性的名称组成的数组,包括可枚举的和不可枚举的.
9.JS提供一个特殊的存储器属性,它不同于"数据属性","数据属性"只是一个简单的值,"存储器属性',则由一个或者两个方法组成,两个方法是getter和setter,例如:
var p ={ x:1, y:2, get r{return math.sqrt(this.x*this.x+this.y*this.y);}, set r(newvalue){ var oldvalue = math.sqrt(this.x*this.x+this.y*this.y) var ratio = newvalue/oldvalue this.x*=ratio this.y*=ratio } }
当我们调用p.r属性的时候
console.log(p.r)//调用get r方法 p.r=5//调用set r方法
10.
属性具有四个特性:对于"数据属性"来说,分别是值,可写行,可枚举性,可配置性.对于"存储器属性"来说,分别是读取(get),写入(set),可枚举性,可配置性.JS定义了一个"属性描述符"(property descriptor)的对象来代表属性的四个属性.描述符对象的属性跟属性特性是同名的.即:数据属性描述符:"value""writable""enumerable""configurate",存储器属性描述符:"get""set""enumerable""configurate".其中get set是函数值,其余的都是布尔值
通过Object.getOwnPropertyDescriptor()可以获得某个对象特定属性的属性描述符(如果是继承属性或者属性不存在,返回undefined):
如: Object.getOwnPropertyDescriptor({x:1},"x") //获取{x:1}对象的x属性的描述符,返回{balue:0,writable:true,enumerable:true,configurable:true}
如果获取继承属性,需要用getPrototypeOf().
如果设置属性的特性,则需要用Object.defineProperty(),
Object.definePeoperty(o,"x",{writable:false,configurable:true}) //设置o对象的x属性不可修改不可配置
如果设置多条属性的话,就用Object.definedPropeties(),例如:
object.defineProperties(o,{
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,
configuable:true
}
})
11.对象的三个属性
原型属性,类属性,可扩展性
ECMAScript5中可以使用Object.getPropertyOf(x)来获取x的原型. 判断一个对象是否是另一个对象的原型用x.IsPropertyOf(y)
类属性是用来表示对象类型信息的一个字符串,作者提供了一个获得对象类属性的一个方法:
function classOf(o){ if(o===null) return null; if(o===undefined) return undefined; return Object.prototype.toString.call(o).sclice(8,-1); }
可配置性用来表示是否能够给对象添加新的属性.ECMAScript用Object.exExtensible(x)可以获得x对象是否是可配置的,通过Object.preventExtensions(x)可以将x对象设置为不可配置的,不可配置以后对象x就不能再添加新的属性.对象被设定为不可配置以后,是不能再被设定为配置了的.
Object.seal()与Object.freeze()方法与Object.preventExtensions()的作用效果相似,但是Object.seal(x)是将对象x"封闭"起来,"封闭"以后x除了设置为不可拓展的以外,x的所有属性都被设置成了不可配置的,也即使不能给这个对象设置新的属性了,同时他已有的属性也不能删除和配置,但是它的可写属性依然可以设置.而Object.freeze(x),"冻结对象,"除了将对象x设置为"封闭"状态外,还将所有数据属性设置为"只读"(如果存储器属性有setter,则存储器属性不受影响).可以用Object.isSeal(x)和Object.isFreeze(x)来判断对象x是否是"封闭"和"冻结"的.
12对象的序列化
JS提供了JSON.stringify()和JSON.parse()方法来将一个对象序列化成JSON格式的字符串和还原,JSON.stringify()方法只支持对象,数组,字符串,无穷大数字,true,false,null.
13.对象的一些方法
toString()
toLocaleString()
toJSON()
valueOf()
据说是在第九章详细介绍的,暂且先放着吧.