自己看书的一点总结,并不一定适合大家,建议大家还是去看看犀牛书
一、对象
对象的特性
- 对象的原型:指向另外一个对象,本对象的属性继承自它的原型对象
- 对象的类: 是一个标识对象类型的字符串
- 对象的扩展标记 : 指明了是否可以向该对象添加新的属性
文章最后在一一介绍。
对象的分类
- 内置对象(native):由ECMAscript规范定义的对象或类。
- 宿主对象(host):由JavaScrit解释器所嵌入的宿主环境定义的,比如浏览器的Window、location
- 自定义对象(user-defined)是由运行中的JavaScrit代码创建的对象
属性的分类
- 自有属性: 自己声明的属性,比如{x:1}中的x
- 继承属性:继承的属性,比如var a ={}中的proto属性
属性的特征:可写、可枚举、可配置、有对应的值
对象的创建
1 . 对象直接量
即使用var a = {b: 1};
的方式创建,对象直接量是一个表达式,其写法等价于 var a = new Object({b: 1})
2 . 通过new创建
关键字new后面跟随一个函数调用,这里的函数称为构造函数,用于初始化一个对象,这里贴一个java的构造函数:
public class A{
public A(){ // 我就是构造函数啦
System.out.println("调用了无参的构造函数");
}
public A(String mess){ //我也是构造函数哦
System.out.println("调用了有参的构造函数\n"+
"参数内容为:"+mess);
}
}
JS:
Function Foo(){ //可以把我看成构造函数
this.s = 1;
}
但是在JavaScrit中,使用Function创建一个对象,同时也创建了他的构造函数。Java中创建一个对象A a1 = new A()
,JS中var obj = new Foo()
。
3 . Object.create()
原型
简单概述一下原型,通过方法1创建的对象都具有同一个原型对象,即Object.prototype
通过方法2创建的对象的原型就是构造函数的prototype属性的值。也有没有原型的对象,Object.prototype
就是其中之一。
使用Object.create()创建对象接收两个参数,第一个参数是对象的原型,第二个参数是可选参数,用以对对象的属性进行进一步描述。
语法:
Object.create(proto, [ propertiesObject ])
例子
o = Object.create(Object.prototype, {
// foo会成为所创建对象的数据属性
foo: { writable:true, configurable:true, value: "hello" },
// bar会成为所创建对象的访问器属性
bar: {
configurable: false,
get: function() { return 10 },
set: function(value) { console.log("Setting `o.bar` to", value) }
}})
二、属性
属性的查询和设置
** 获取属性的值**
- 使用点运算符
- 使用方括号运算符
var a = jack.name,b = jack['age']
关联数组:使用方法2来获取属性的值,看起来很像数组,但是是以字符串索引而不像数组使用数字索引,这种数组就叫做关联数组。
<u>什么情况下使用方法2?</u>
属性与关键字重名,或需要拼接属性名的时候。例子:
var i = 1;
var a = today['date'];
var a = today['goods'+i];
继承
继承理解起来非常简单,比如对象A有一个属性x,对象B继承自对象A,那么对象B就会继承对象A的x属性,但是如果对象B自己有一个x属性,那么B将不会继承对象A的x属性,在对象B上修改x属性的值,不会影响到对象A的x属性。如果要查询对象B的x如果B有x属性就返回B的x属性,如果B没有x属性就会向B的原型上查找,在A中找到了x属性就返回x,否则继续向上直到没有查到返回null。
这里挖一个坑,一个具有setter方法的accessor属性以后填
属性访问错误
获取属性的值时book.title
如果book对象没有title属性那么将返回undefined,在这种情况下使用book.title.length
就会报错:undefined没有length属性。除非确定book和book.title都是对象,否则不能这样写表达式。说了那么多就是为了推荐使用下面的方法,在不能确定book和book.title是不是对象的时候。
var len = book && book.title &&book.title.length;
删除属性
delete可以删除对象的属性,delete只是断开属性与宿主的联系,而不会去操作属性中的属性——这句话怎么理解呢?
a={p:{x=1;}}; b=a.p; delete a.p;
看这段代码,删除了a上面的p属性。但是打印b.x的时候仍然返回1,为什么呢?因为已经删除的属性的引用依然存在。怎么避免呢?在销毁对象的时候先遍历删除对象中的属性。
delete表达式删除成功或没有副作用(比如删除不存在的属性)时,返回true。如果delete后面不是一个属性访问表达式,比如delete 1;
也会返回true。
注意
delete不能删除不可配置的属性,即之前提到的属性的可配置性为false的情况,一下是一些方便理解的例子:
delete Object.prototype; //不能删除,属性不可配置
var x = 1; delete this.x //不能删除全局变量
function f(){}; delete f(); //不能删除一个全局函数
检测属性
有时候,经常会检测属性是否在对象中,可以使用一下三种方法:
in运算符:如果对象的自由属性和继承属性中包含这个属性就返回true
"x" in Object; // 返回true或false
hasOwnProperty()方法:检测对象的属性是否为自有属性
Object.hasOwnProperty(“x”); // 返回true或false
propertyIsEnumberable()方法: 检测对象的属性是否为自有属性且可枚举性为是否为true,都为true则返回true。
Object.propertyIsEnumberable(“x”);
一个小贴士:
可使用‘!==’判断一个属性是否是undefined,可以当作in运算符来使用,但是当属性的值为undefined时,即{x = undefined}
,使用‘!==’会返回true,就只能用in运算符。
为什么是"!== "而不是" !="?因为"!=="可以区分null 和undefined。
枚举属性
枚举嘛,就是遍历咯。通常使用for/in循环来遍历。但是for/in循环只能遍历可枚举的属性(包括自有属性可继承属性),把属性名称赋值给循环变量。
还有俩方法:
- Object.keys(); 返回一个数组,该数组由对象中可枚举的自有属性的名称组成
- Object.getOwnpropertyName(); 返回对象所有的自有属性。
如果有些自定义的属性我不想遍历?
转换为不可枚举属性:o.propertyInEnumberable("x");
如果我需要遍历所有属性?
Object.getOwnpropertyName();遍历所有的自有属性,继承属性就遍历他的父级
如果我只想遍历继承属性?
加上判断,跳过自由属性就可以啦:if(obj.hasOwnProperty(p)) continue;
属性getter和setter
对象是由名字、值和一组特性构成的。而其中的属性值可以用一个或两个方法替代,那就是getter和setter——这样定义的属性叫“存储器属性”。
先上例子:
var obj = {
a:"hello",
get b(){ return "NMBD" },
set b(newValue){this.a = newValue},
c: "ketty"
}
console.log(obj.b); //NMBD
console.log(obj.a+obj.b) // hello ketty
obj.b = "Q";
console.log(obj.a+obj.b+obj.c)//QNMBDketty
上面的例子表名,set方法就是用来设置已存在的属性的值的。你可以设置多个,关键看你函数体怎么写。get方法返回一个什么都可以。关键还是看你想做o(゚Д゚)っ啥!(输入法卖萌了......)
那么,要是继承了一个拥有getter和setter方法的对象,会继承他的getter和setter吗?
存储器属性也是可以继承滴。和使用其他属性一样使用就可以了。
例子:
var test = Object.create(obj); //继承自上个例子的obj
console.log(test.b); // NMBD
test.b = "hahaha";
console.log(test.a); //hahaha
感觉这东西用处不大啊?
等以后想出好点子再来填吧。
属性的特征
之前说的属性有三个特征:** 可写、可枚举、可配置,其实还有一个就是值。**
但是上面介绍的setter和getter属性所具备的特征就有点不一样了,分别为读取,写入,可枚举性和可配置性。
下面列举一下这三个特征相关的API。
1.Object.getOwnPropertyDescriptor()只可获得自有属性的属性描述符。
Object.getOwnPropertyDescriptor({x:1},"x");//接收两个值
Object {value: 1, writable: true, enumerable: true, configurable: true}
2.Object.defineProperty()设置属性的特性。需要传入三个参数,第一个为对象,第二个为要修改的属性,第三个为要修改的属性的属性描述符(一个对象,不必包含4个特性)。第二个参数和第三个参数可以整合到一起传。
Object.defineProperty(obj,x,{
value: 1,
writable: true,
enumerable: false,
configurable: true});
//如果属性是getter,第三个参数为
{
get: function(){ 函数体},enumerable: true,configurable: true
}
//第二个参数和第三个参数整合
Object.defineProperty(obj,{
x:{
value: 1,
writable: true,
enumerable: false,
configurable: true},
y:{.......}
});
补充
看完了如果觉得不过瘾,再来看看这里。
对象的三个属性
前面提到过对象的三个属性:原型、类、扩展标记。
1、 原型
上面已经有简单的介绍了原型,这里介绍一个方法:isPropertyOf();判断原型是否是XXXX。
obj.isPropertyOf(a); //true,a继承自obj(这里的继承容易混淆)。
有一个属性__proto__
,用于直接查询/设置对象的原型。不推荐使用。
但是使用起来很简单obj.__proto__
查询。obj.__proto__= null
设置。
2、类
对象的类属性是一个字符串,用于表示对象的类型信息。使用toString()方法可返回对象的类属性。但不是直接obj.toString()
。而是
var a = {x:1}
console.log(a.toString().slice(8,-1))
3、可扩展
可扩展性用于表示是否可以给对象添加新属性。所有的内置对象和自定义对象都是可扩展的。而宿主对象是否可扩展取决于JavaScrit引擎。
下面介绍查询和设置对象的可扩展性的函数。
-
Object.esExtensible(obj);
传入对象obj判断是否为可扩展的。
Object.preventExtensions(obj);
传入对象obj设置其为不可扩展的,注意设置了之后就无法再转换为可扩展的了。 -
Object.seal(obj)
传入对象obj设置其为不可扩展的并且将自有属性都设置为不可配置的,也就是说不能添加属性也不能修改或删除。和上个函数一样也不能解封。
Object.isSealed(obj)
检测对象是否封闭。 -
Object.freeze(obj)
看名字冻结,很恐怖的级别。不可扩展、属性不可配置、属性只读(存取器属性(setter)不受影响)。
object.isFreeze(obj)
检测对象是否冻结
序列化对象
序列化对象是指将对象的状态转化为字符串,也可将字符串还原为对象。
用到的函数:
- JSON.stringify(); //序列化对象,只能序列化对象可枚举的自有属性
- JSON.parse(); //还原对象
下面是例子:
var a = {x:2,y:3,z:{j:4}};
var s = JSON.stringify(a);//'{{"x":2,"y":3,"z":{"j":4}}}'
var b =JSON.parse(s); //b是a的深拷贝
上面提到了深拷贝。什么是深拷贝?
用比较容易理解的说法,对象b拷贝一个对象a,修改b的属性值a中的也会改变就是浅拷贝。修改b的值a的值不会受影响就是深拷贝。
想了解更多请google或BD mother。
对象的方法
JavaScrit的所有对象都是从Object.prototype继承属性。继承的属性大多都是方法,像之前提到的hasOwnPerperty()、isPropertyOf()等。
下面介绍几个常用的方法。
toString()方法
它将返回一个表示调用这个方法的对象值的字符串。不同的数据类型返回的值都不同。
array.toString(); // 返回一个数组元素列表[hehe,haha,]==>hehe,haha
date.toString(); //返回一个时间==>Wed Jul 20 2016 16:00:38 GMT+0800 (中国标准时间)
function.toString(); // 返回整个函数的源代码。
toLocaleString()方法
返回一个表示这个对象的本地化字符串。
所谓的本地化就是不同的地区有其本地的习惯,比如时间显示在美国,toLocaleString 可能会返回 "03/21/08 01:02:03",而在欧洲,返回值则可能是 "21/03/08 01:02:03",因为欧洲的惯例是将日期放在月份前面。
其中Date和Number类对toLocaleString()方法作了定制。具体怎么定制书中没有提及。
toJSON()方法
书中的描述实在是有点让我小小失望了一下啊,还以为是个什么牛逼的方法。。。。
toJSON()方法是用来给JSON.stringify()调用的,实际上Object.Property没有定义toJSON这个方法。
http://www.zhihu.com/question/23672102 贴一个回答,方便理解。觉得好帮他点赞吧。
valueOf()方法
与toString()方法非常相似,往往在需要将对象转化为某种原始值才调用它。尤其是转化为数字的时候。此方法需要详细介绍请移步至:http://www.cnblogs.com/chyingp/archive/2013/02/22/valueOf.html
以上就是对象的所有阅读笔记啦,谢谢观赏。