读《JavaScript权威指南》笔记(三)--对象

时间:2022-08-27 08:14:07

1.对象介绍

对象是JavaScript的基本数据类型。对象是一种复合值:它将很多值(原始值或者其他对象)聚合在一起,可通过名字访问这些值。对象也可看做是属性的无序集合,每个属性都是一个名/值对。属性名是字符串,因此我们可以把对象看成是从字符串到值的映射。
由于JavaScript是弱类型语言,因此不必遵循这条规定,在任何对象中程序都可以创建任意数量的属性。除了字符串、数字、true、false、null和undefined之外,JavaScript中的值都是对象。

2.对象属性的操作

1)对象对于点(.)来说,右侧必须是一个以属性名称命名的简单标识符。对于方括号来说([]),方括号内必须是一个计算结果为字符串的表达式,这个字符串就是属性的名字

2)使用方括号和一个字符串,看起来更像数组,只是这个数组元素是通过字符串索引而不是数字索引。这种数组就是我们所说的关联数组,也称做散列、映射或字典JavaScript对象都是关联数组

3)由于在写程序的时候不知道属性名称,因此无法通过点运算符(.)来访问对象portfolio的属性。但可以使用[]运算符,因为它使用字符串值(字符串值是动态的,可以在运行时更改)而不是标识符(标识符是静态的,必须写死在程序中)作为索引对属性进行访问。

4)delete运算符只能删除自有属性,不能删除继承属性

5)在这些场景下给对象o设置属性p会失败:

· o中的属性p是只读的:不能给只读属性重新赋值(defineProperty()方法中有一个例外,可以对可配置的只读属性重新赋值)。
· o中的属性p是继承属性,且它是只读的:不能通过同名自有属性覆盖只读的继承属性。
· o中不存在自有属性p:o没有使用setter方法继承属性p,并且o的可扩展性(extensible attribute)是false(参照6.8.3节)。如果o中不存在p,而且没有setter方法可供调用,则p一定会添加至o中。但如果o不是可扩展的,那么在o中不能定义新属性。

6)属性赋值要么失败,要么创建一个属性,要么在原始对象中设置属性,但有一个例外,如果o继承自属性x,而这个属性是一个具有setter方法的accessor属性,那么这时将调用setter方法而不是给o创建一个属性x。需要注意的是,setter方法是由对象o调用的,而不是定义这个属性的原型对象调用的。因此如果setter方法定义任意属性,这个操作只是针对o本身,并不会修改原型链。

var unitcircle = { r:1 };      // 一个用来继承的对象
var c = inherit(unitcircle); // c继承属性r
c.x = 1; c.y = 1;              // c定义两个属性
c.r = 2;                       // c覆盖继承来的属性
unitcircle.r;                  // => 1,原型对象没有修改

3.对象的继承

假设要查询对象o的属性x,如果o中不存在x,那么将会继续在o的原型对象中查询属性x。如果原型对象中也没有x,但这个原型对象也有原型,那么继续在这个原型对象的原型上执行查询,直到找到x或者查找到一个原型是null的对象为止。可以看到,对象的原型属性构成了一个“链”,通过这个“链”可以实现属性的继承。

现在假设给对象o的属性x赋值,如果o中已经有属性x(这个属性不是继承来的),那么这个赋值操作只改变这个已有属性x的值。如果o中不存在属性x,那么赋值操作给o添加一个新属性x。如果之前o继承自属性x,那么这个继承的属性就被新创建的同名属性覆盖了。属性赋值操作首先检查原型链,以此判定是否允许赋值操作。例如,如果o继承自一个只读属性x,那么赋值操作是不允许的。如果允许属性赋值操作,它也总是在原始对象上创建属性或对已有的属性赋值,而不会去修改原型链。在JavaScript中,只有在查询属性时才会体会到继承的存在,而设置属性则和继承无关,这是JavaScript的一个重要特性,该特性让程序员可以有选择地覆盖(override)继承的属性。

4.循环对象

for/in循环对象的可枚举的属性,包括自身和继承的属性;
Object.keys()它返回一个数组,这个数组由对象中可枚举的自有属性的名称组成;
Object.getOwnPropertyNames(),它和Ojbect.keys()类似,只是它返回对象的所有自有属性的名称,而不仅仅是可枚举的属性

5.判断某个属性是否存在于某个对象中

判断某个属性是否存在于某个对象中。可以通过in运算符、hasOwnPreperty()和propertyIsEnumerable()方法来完成这个工作,甚至仅通过属性查询也可以做到这一点。

1)in运算符的左侧是属性名(字符串),右侧是对象。如果对象的自有属性或继承属性中包含这个属性则返回true:

var o = { x: 1 }
"x" in o;             // true:"x"是o的属性
"y" in o;             // false:"y"不是o的属性
"toString" in o;      // true:o继承toString属性

2)对象的hasOwnProperty()方法用来检测给定的名字是否是对象的自有属性。对于继承属性它将返回false:

var o = { x: 1 }
o.hasOwnProperty("x"); // true:o有一个自有属性x
o.hasOwnProperty("y"); // false:o中不存在属性y
o.hasOwnProperty("toString"); // false:toString是继承属性

3)propertyIsEnumerable()是hasOwnProperty()的增强版,只有检测到是自有属性且这个属性的可枚举性(enumerable attribute)为true时它才返回true。某些内置属性是不可枚举的。通常由JavaScript代码创建的属性都是可枚举的

4)另一种更简便的方法是使用“!==”判断一个属性是否是undefined

var o = { x: 1 }
o.x !== undefined; //true: o中有属性x
o.y !== undefined; // false: o中没有属性y
o.toString !== undefined; //true: o继承了toString属性

未完...