/* 对象字面量 */
var empty_object = {};
var stooge = {
"first-name": "Jerome",
"last-name": "Howard"
};
var flight = {
airline: "Oceanic",
number: 815,
departure: {
IATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: {
IATA: "LAX",
time: "2004-09-23 10:55",
city: "Los Angeles"
}
};
/* 检索 */
stooge["first=name"]; // "Joe"
flight.departure.IATA; // "SYD"
/* 检索不存在将返回一个 undefined 值 */
stooge["middle-name"]; // "undefined"
/* || 运算符可以用来填充默认值 */
var middle = stooge["middle-name"] || "(none)";
/* 尝试检索一个 undefined 值将会导致TypeError 异常,可以通过 && 运算符避免 */
flight.equipment; // undefined
flight.equipment.model; // throw "TypeError"
flight.equipment && flight.equipment.model //undefined
/* 更新 */
stooge["first-name"] = "Jerome";
/* 扩充属性 */
stooge['middle-name'] = 'Lester';
stooge.nickname = 'Curly';
flight.equipment = {
medel: 'Boeing 777'
};
flight.status = 'overdue';
/* 引用 */
var x = stooge;
x.nickname = 'Curly';
var nick = stooge.nickname; // 因为 x 和 stooge 是指向同一个对象的引用,所以 nick 为 'Curly'
var a = {}, b = {}, c = {}; //a,b,c 每个都引用一个不同的空对象
a = b = c = {}; //a,b,c 都引用同一个空对象
/* 原型 */
/*
每个对象都连接到一个原型对象,并且它可以从中继承属性。所有通过对象字面量创建的对象都连接到
Object.prototype 这个JavaScript 中标准的对象。
当你创建一个新对象时,你可以选择某个对象作为它的原型对象。JavaScript 提供的实现机制杂乱而
复杂,但其实它可以被明显的简化。我们将给 Object 增加一个 beget 方法。这个 beget 方法创建
一个使用原对象作为其原型的新对象。
*/
if (typeof Object.beget !=== 'function') {
Object.beget = function(o) {
var F = function() {};
F.prototype = o;
return new F();
};
}
var anothor_stooge = Object.beget(stooge);
/*
原型连接在更新时是不起作用的。当我们对某个对象做出改变时,不会触及到该对象的原型:
*/
anothor_stooge['first-name'] = 'Harry';
anothor_stooge['middle-name'] = 'Moses';
anothor_stooge.nickname = 'Moe';
/*
原型连接只有在检索值的时候才被用到。如果我们尝试去获取对象的某个属性值,且该对象没有此属性
名,那么 JavaScript 会尝试着从原型对象中获取属性值。如果那个原型对象也没有该属性,那么再从
它的原型中寻找,依次类推,知道该过程最后到达终点 Object.prototype。如果想要的属性完全不存在
于原型链中,那么结果就是undefined值。这个过程称为委托。
原型关系是一种动态的关系。如果我们添加一个新的属性到原型汇中,该属性会立即对所有基于该原型
创建的对象可见。
*/
stooge.profession = 'actor';
anothor_stooge.profession; // 'actor'
/* 反射 */
/*
检查对象并确定对象有什么属性是很容易的事情,只要试着去检索该属性并验证取得的值。
typeof 操作符对确定属性的类型很有帮助:
*/
typeof flight.number; // 'number'
typeof flight.status; // 'string'
typeof flight.arrival; // 'object'
typeof flight.manifest; // 'undefined'
/* 请务必注意原型链中任何属性也会产生一个值 */
typeof flight.toString(); // 'function'
typeof flight.constructor; // 'function'
/*
有两个方法去处理这些不需要的属性。第一个是让你的程序检查并剔除函数值。一般来说,
做反射的目标是数据,因此你应该意识到一些值可能会是函数。
另一个方法是使用 hasOwnProperty 方法,如果对象拥有独有的属性,它将返回 true 。
hasOwnProperty 方法不会检查原型链。
*/
flight.hasOwnProperty('number'); //true
flight.hasOwnProperty('constructor'); //false
/* 枚举 */
/*
for in 语句可用来遍历一个对象中的所有属性名。该枚举过程将会列出所有的属性——
包括函数和你可能不关心的原型中的属性——所以有必要过滤掉那些你不想要的值。
最为常用的过滤器是 hasOwnProperty 方法,以及使用 typeof 来排除函数:
*/
var name;
for(name in anothor_stooge) {
if (typeof anothor_stooge[name] !== 'function') {
document.writeln(name + ': ' + anothor_stooge[name]);
}
}
/*
属性名出现的顺序是不确定的,因此要对任何可能出现的顺序有所准备。如果你想要确保
属性以特定的顺序出现,最好的办法就是完全避免使用 for in 语句,而是创建一个数组,
在其中以正确的顺序包含属性名:
*/
var i;
var properties = [
'first-name', 'middle-name', 'last-name', 'profession'
];
for(i = 0; i < properties.length; i += 1) {
document.writeln(properties[i] + ': ' + anothor_stooge[properties[i]]);
}
/*
通过使用 for 而不是 for in,可以得到我们想要的属性,而不用担心可能发掘出原型链中
属性,并且我们按正确的顺序缺的它们的值。
*/
/* 删除 */
/*
delete 运算符可以用来删除对象的属性。它将会移除对象中确定包含的属性。它不会触及
原型链中的任何对象。
删除对象的属性可能会让来自原型链中的属性浮现出来:
*/
anothor_stooge.nickname; // 'Moe'
// 删除 anothor_stooge 的 nickname 属性,从而暴露原型的 nickname 属性
delete anothor_stooge.nickname;
anothor_stooge.nickname; // 'Curly'
/* 减少全局变量的污染 */
/*
JavaScript 可以很随意地定义那些可保存所有的应用资源的全局变量。不幸的是,全局变量削弱
了程序的灵活性,所以应该避免。
最小化使用全局变量的一个方法是在你的应用中只创建唯一一个全局变量:
*/
var MYAPP = {};
/*
该变量此时变成了你的应用容器:
*/
MYAPP.stooge = {
"first-name": "Joe",
"last-name": "Howard"
};
MYAPP.flight = {
airline: "Oceanic",
number: 815,
departure: {
IATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: {
IATA: "LAX",
time: "2004-09-23 10:55",
city: "Los Angeles"
}
};
/*
只要把多个全局变量都整理在一个命名空间下,你将显著降低与其他应用程序,组件或类库之间产生
糟糕的互相影响的可能性。你的程序也会变得更容易阅读,因为很明显 MYAPP.stooge 指向的是顶层
结构。
使用闭包来进行信息隐藏的方式是另一个有效减少全局污染的方法。
*/
如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛