看犀牛书的笔记——对象

自己看书的一点总结,并不一定适合大家,建议大家还是去看看犀牛书

一、对象

对象的特性

  1. 对象的原型:指向另外一个对象,本对象的属性继承自它的原型对象
  2. 对象的类: 是一个标识对象类型的字符串
  3. 对象的扩展标记 : 指明了是否可以向该对象添加新的属性

文章最后在一一介绍。

对象的分类

  1. 内置对象(native):由ECMAscript规范定义的对象或类。
  2. 宿主对象(host):由JavaScrit解释器所嵌入的宿主环境定义的,比如浏览器的Window、location
  3. 自定义对象(user-defined)是由运行中的JavaScrit代码创建的对象

属性的分类

  1. 自有属性: 自己声明的属性,比如{x:1}中的x
  2. 继承属性:继承的属性,比如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) }
}})

二、属性

属性的查询和设置

** 获取属性的值**

  1. 使用点运算符
  2. 使用方括号运算符
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循环只能遍历可枚举的属性(包括自有属性可继承属性),把属性名称赋值给循环变量。

还有俩方法:

  1. Object.keys(); 返回一个数组,该数组由对象中可枚举的自有属性的名称组成
  2. Object.getOwnpropertyName(); 返回对象所有的自有属性。

如果有些自定义的属性我不想遍历?
转换为不可枚举属性:o.propertyInEnumberable("x");
如果我需要遍历所有属性?
Object.getOwnpropertyName();遍历所有的自有属性,继承属性就遍历他的父级
如果我只想遍历继承属性?
加上判断,跳过自由属性就可以啦:if(obj.hasOwnProperty(p)) continue;

属性getter和setter

对象是由名字、值和一组特性构成的。而其中的属性值可以用一个或两个方法替代,那就是gettersetter——这样定义的属性叫“存储器属性”
先上例子:

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引擎。
下面介绍查询和设置对象的可扩展性的函数。

  1. Object.esExtensible(obj);传入对象obj判断是否为可扩展的。
    Object.preventExtensions(obj);传入对象obj设置其为不可扩展的,注意设置了之后就无法再转换为可扩展的了
  2. Object.seal(obj)传入对象obj设置其为不可扩展的并且将自有属性都设置为不可配置的,也就是说不能添加属性也不能修改或删除。和上个函数一样也不能解封。
    Object.isSealed(obj)检测对象是否封闭。
  3. Object.freeze(obj)看名字冻结,很恐怖的级别。不可扩展、属性不可配置、属性只读(存取器属性(setter)不受影响)
    object.isFreeze(obj)检测对象是否冻结

序列化对象

序列化对象是指将对象的状态转化为字符串,也可将字符串还原为对象。
用到的函数:

  1. JSON.stringify(); //序列化对象,只能序列化对象可枚举的自有属性
  2. 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

以上就是对象的所有阅读笔记啦,谢谢观赏。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容