#对象
- JS简单类型:数字、字符串、布尔值(true 和 false)、null值和undefined值。
- 其他所有值都是对象。
- 数组是对象,函数事对象,正则表达式是对象,当然,对象也是对象。
- Prototype(原型链):允许对象继承另一个对象的属性。正确的使用它,能减少对象初始化时消耗的时间和内存。
###对象字面量
- 对象字面量提供了一种非常方便的创建新对象值得表示法。
- 对象字面量就是包围在一对花括号中的零或多个“名/值” 对。
- 对象字面量出现在任何允许表达式出现的地方
例如:
var empty_obj = {};
var stooge = {
'first_name' : 'cm',
'last_name' : 'liang'
};
- 属性名可以是包括空字符串在内的任何字符串;
- 在字面量中,如果属性名是一个合法的JS标识且不是保留字,则并不强求用引号括住属性名;
- 逗号是用来分隔多个“名/值”对;
- 属性值可以从包括另一个对象字面量在内的任意表达式中获得。
var flight = {
airline: 'Oceanic',
number: 815,
departure: {
IATA: 'SYD',
time: '2014-01-01',
city: 'GZ'
},
arrival: {
IATA: 'LAX',
time: '2013-01-01',
city: 'SZ'
}
};
###检索
- 检索对象中包含的值,有两种方式: * 1.在[]后缀中括住一个字符串表达式的方式。 * 2.优先考虑的方法,使用 . 表示法,它更紧凑且可读性更好。
例如:
stooge['first_name']; //cm
flight.arrival.city; //SZ
- 检索一个不存在的成员元素的值,返回“undefined”。
例如:
stooge['middle_name']; //undefined
flight.goWhere; //undefined
- ||用来填充默认值
例如:
var middle = stooge['middle_name'] || '(none)';
middle; //"(none)"
var status = flight.status || 'unknown';
status; //unknown
- 检索一个undefined值会导致TypeError异常。可以通过&&运算符来避免错误。
stooge.address; //undefined
stooge.address.language; //throw "TypeError"
stooge.address && stooge.address.language; //undefined
###更新
- 对象中的值可以通过赋值语句来更新。
- 如果属性名已经存在对象中,那个这个属性值会被替换。
例如:
stooge.first_name = "elly";
stooge.first_name; //"elly"
- 如果对象中没有那个属性名,那么该属性就被扩充到该对象中。
例如:
empty_obj.nickname = 'John';
empty_obj.nickname; //"John"
flight.equipment = {
model: 'MH370'
};
flight.equipment.model; //"MH370"
###引用
- 对象通过引用来传递,永远不会被拷贝。
例如:
var x = empty_obj; //将x赋值给empty_obj对象
x.hobby = 'movie';
var hob = empty_obj.hobby; //"movie"
//or var hob = x.hobby; //"movie"
- x和empty_obj是指向同一个对象的引用,所以x.hobby 和 empty_obj.hobby为"movie"。
例如:
var a={},b={},c={};
//a、b和c都引用一个不同的空对象
a = b = c = {};
//a、b和c都是引用同一个空对象
###原型
- 每个对象都连接到一个原型对象,并且它可以从中继承属性。
- 所有通过对象字面量创建的对象都连接到Object.prototype这个JS中标准的对象。
- 当你创建一个新对象时,可以选择某个对象作为它的原型。
- 原型连接在更新时是不起作用的。当对某个对象做出改变时,不会触及到该对象的原型。
例如:
var stooge = {
nickname: 'elly'
};
if(typeof Object.beget !== 'function'){
Object.beget = function(o){
var F = function(){};
F.prototype = o;
return new F();
};
}
var another_stooge = Object.beget(stooge);
another_stooge.nickname = 'cm';
stooge.nickname; //"elly"
another_stooge.nickname; //"cm"
- 原型连接只有在检索值的时候才被用到。
- 如果我们尝试去获取对象的某个属性值,且该对象没有此属性名,那么JS会尝试从原型对象中获取属性值。
- 如果那个原型对象也没有该属性,那么再从它的原型中寻找,依次类推,知道该过程最后到达终点Object.prototype。
- 如果想要的属性完全不存在于原型链中,那么结果就是undefined。
- 这个过程称为委托
- 原型关系是一种动态的关系。
- 如果我们添加一个新的属性在原型中,该属性会立即对所有基于该原型创建的对象可见。
例如:
stooge.profession = 'actor';
another_stooge.profession; //'actor'
###反射
- 检查对象并确定对象的属性,只要试着去检索该属性并验证取得的值。
- typeof可以确定属性的类型
例如:
typeof stooge.profession; //'string'
- 请务必注意,原型链中的任何属性也会产生一个值
例如:
typeof flight.toString; //'function'
typeof flight.constructor; //'function'
- 有两种方法处理这些不需要的属性 * 第一个是让你的程序检查并剔除函数值 * 第二个是使用hasOwnProperty方法。注意:如果对象拥有独有的属性,它将返回true。hasOwnProperty方法不会检查原型链
例如:
flight.hasOwnProperty('number'); //true
flight.hasOwnProperty('constructor'); //false
###枚举(for in)
- for in语句可用来遍历一个对象中的所有属性名。
- 枚举过程将会列出所有的属性,包括函数和你可能不关心的原型中的属性,所以有必要多虑掉那些你不想要的值。
- 最常用的过滤器是hasOwnProperty方法,以及使用typeof来排除函数。
例如:
var name;
for(name in another_stooge){
if(typeof another_stooge[name] !== 'function'){
document.writeln(name + ':' + another_stooge[name]);
}
}
- for in语句陈列出来的属性名顺序是不确定的,如果你想让属性名按顺序出现,最好的办法就是避免使用for in语句。
- 而是创建一个数组,在其中以正确的顺序包含属性名。
例如:
var i;
var properties = {
'first_name',
'profession'
};
for(i = 0; i < properties.length; i += 1){
document.writeln(properties[i] + ':' + another_stooge[properties[i]]);
}
- 使用for,可以得到我们想要的属性,不用担心可能发掘出原型链中的属性,并且按顺序取得了它们的值。
###删除(delete)
- delete运算符用来删除对象的属性,它不会触及原型链中的任何对象。
another_stooge.nickname; //'cm'
delete another_stooge.nickname;
another_stooge.nickname; //暴露出原型中nickname属性。'elly'
###减少全局变量污染
- 全局变量削弱程序的灵活性,所以尽量避免。
- 最小化用全局变量的一个方法是在你的应用中只创建唯一一个全局变量。
例如:
var MYAPP = {};
//此时,全局变量已经变成了你的容器
MYAPP.stooge = {
'first_name' : 'cm',
'last_name' : 'liang'
};
MYAPP.flight = {
'airline' : 'Oceanic',
};
- 只要把多个全局变量都整理在一个名称空间下,你将显著降低与其他应用程序、组件或类库之间产生糟糕的相互影响的可能性。
- 你的程序也会变得更容易阅读。