第三章 对象(JavaScript:语言精粹)
对象是属性的容器,其中每个属性都有名字和值。
一个对象字面量,就是包围在一对花括号中的零个或多个“名/值”对。
// 3.1 code 1 var empty_object = {}; var stooge = { "first-name": "Jerome", "last-name": "Howard" };
对象可以是嵌套的:
// 3.1 code 2 var filght = { airline: "Oceanic", number: 815, departure: { IATA: "SYD", time: "2004-09-22 14:55", city: "Sydney" }, arrival: { IATA: "LAX", time: "2004-09-23 10:42", city: "Los Angeles" } }
检索对象里包含的值,有两种方式:[] 和 . 。
// 3.2 code 3 stooge["first-name"] // "Jerome" flight.departure.IATA // "SYD"
检索不存在的成员属性的值,将返回 undefined 。
// 3.2 code 4 stooge["middle-name"] // undefined flight.status // undefined stooge["FIRST-NAME"] // undefined
用 || 运算符设置默认值:
// 3.2 code 5 var middle = stooge["middle-name"] || "(none)"; var status = flight.status || "unknown";
用 && 运算符避免错误:
// 3.2 code 6 flight.equipment // undefined flight.equipment.model // throw "TypeError" flight.equipment || flight.equipment.model // undefined
对象里的值可以通过赋值语句来更新。
stooge['first-name'] = "Jerome"; stooge['middle-name'] = "Lester"; flight.equipment = { model: "Boeing 777" }; flight.status = "overdue";
如果属性名存在,属性值会被替换;如果属性名不存在,这个属性会被扩展到对象中。
对象通过引用来传递。
// 3.4 code 8 var x = stooge; x.nickname = "Curly"; stooge.nickname; // "Curly" var a = {}, b = {}, c = {}; // refer the diff Object a = b = c = {}; // refer the same Object
所有通过字面量创建的对象都连接到 Object. prototype。
我们给 Object 增加一个 create 方法,用这个方法创建一个新对象,这个新对象使用原对象作为它的原型。
// 3.5 code 9 if (typeof Object.beget !== 'function') { Object.create = function (obj) { var Func = function () {}; Func.prototype = obj; return New Func(); }; } var new_stooge = Object.create(stooge);
更新原型的属性值是不可能的,只会覆盖(新添属性名在原型中已经有了)。
// 3.5 code 10 new_stooge['first-name'] = 'Harry'; new_stooge['middle-name'] = 'Moses'; new_stooge.nickname = 'Moses';
更改了原型对象,对 new_stooge 起作用了。
// 3.5 code 11 stooge.profession = 'actor'; new_stooge.profession // 'actor'
用 typeof 操作符确定类型。
// 3.6 code 12 typeof flight.number // 'number' typeof flight.status // 'string' typeof flight.arrival // 'object' typeof flight.manifest // 'undefined'
原型中的属性类型:
// 3.6 code 13 typeof flight.toString // 'function' typeof flight.constructor // 'function'
如果一个属性是一个对象独有的属性,用 hasOwnProperty 方法,将返回 true;如果一个属性是一个对象原型链上的属性,将返回 false。
// 3.6 code 14 flight.hasOwnProperty('number') // true flight.hasOwnProperty('constructor') // false
for in 语句会遍历一个对象中所有的属性名 ---- 包括函数和原型中的属性 ---- 现在你想过滤他们,可以用 hasOwnProperty 方法过滤原型中的属性,用 typeof 来排除函数。
// 3.7 code 15 var name; for (name in new_stooge) { if (typeof new_stooge[name] !== 'function' || !new_stooge.hasOwnProperty(name)) { document.writeln(name + ': ' + new_stooge[name]); } }
但这种遍历出来的属性名顺序不确定。如果想确定,得用到一个数组和 for 语句。
// 3.7 code 16 var i; var properties = [ 'first-name', 'middle-name', 'last-name', 'profession' ]; for (i = 0; i < properties.length; i += 1) { document.writeln(properties[i] + ': ' + new_stooge[properties[i]]); }
delete 语句用来删除对象的属性。
// 3.8 code 17 new_stooge.nickname // 'Moe' object's value delete new_stooge.nickname; new_stooge.nickname // 'Curly' exposed prototype's value
创建一个唯一的全局变量。
// 3.9 code 18 var MYAPP = {};
这个变量变成了你应用的容器:
// 3.9 code 19 MYAPP.stooge = { "first-name": "Jerome", "last-name": "Howard" }; MYAPP.filght = { airline: "Oceanic", number: 815, departure: { IATA: "SYD", time: "2004-09-22 14:55", city: "Sydney" }, arrival: { IATA: "LAX", time: "2004-09-23 10:42", city: "Los Angeles" } }
这样全局的资源纳入了一个命名空间下。
使用闭包来进行信息隐藏的方式,也是一种有效减少全局变量的方法。下面会讲。
(完)