对象
- Javascript中的简单类型:number,string,boolean,null,undefined。
- 其他所有值都是对象。 对象是属性的容器,每个属性都有名字和值。属性的名字可以是任意字符串(包含空字符串),属性值可以是除undefined外的任意值。对象无类别。
对象字面量
创建新对象值 { 名/值 } 属性值可获得
var empty_object = {}; //创建空对象
var stooge = {
"first-name":"Joe",
"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:42",
city:"Los Angeles"
}
}
检索
- 对象[属性名]
stooge["first-name"] //"Joe"
flight.departure.IATA //"STD"
- 检索不存在的属性名的值,将返回undefined
stooge["middle-name"] //undefined
flight.status //undefined
- 使用 || 填充默认值
var middle = stooge["middle-name"] || "(none)";
var status = flight.status || "unknown";
- 使用 && 避免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 = {
model:'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中标准的对象,所有通过对象字面量创建的对象都连接到Object.prototype
- 给Object添加一个beget方法,创建一个使用原对象作为其原型的新对象
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['first-name'] = 'Harry';
another_stooge['middle-name'] = 'Moses';
another_stooge.nickname = 'Moe';
- 原型关系是一种动态关系。在原型中添加新属性,新属性会立即对所有基于该原型创建的对象可见
stooge.profession = 'actor';
another_stooge.profession //'actor'
原型连接只有在检索值时才会被用到。如果我们尝试获取对象的某个属性值,但该对象没有此属性名,那么javascript会尝试从原型对象中获取该属性值。如果这个原型对象也没有该属性,那么再从它的原型中寻找,以此类推,直至该过程到达终点Object.prototype。如果该属性不存在于原型链中,结果将是undefined值。这个过程称为委托。
反射
利用typeof操作符确定属性的类型
typeof flight.number //'number'
typeof flight.arrival //'object'
//原型链中的任何属性也会产生一个值
typeof flight.toString //'function'
如何处理这些不需要的属性
- 让程序检查并剔除函数值
- 使用hasOwnProperty方法,该方法不会检查原型链
//对象拥有独有的属性时返回true
flight.hasOwnProperty('number') //true
flight.hasOwnProperty('constructor') //false
枚举
使用 for in 语句枚举一个对象中的所有属性名,属性名出现的顺序是不确定的。使用 for 可以按照正确的顺序取到他们的值。
// for in
var name;
for (name in another_stooge) {
if (typeof another_stooge[name] != 'function') {
document.writeln(name + ':' + another_stooge[name]);
}
}
// for
var i;
var properties = { //存储another_stooge中存在的属性名
'first-name',
'middle-name',
'last-name',
'profession'
};
for (i = 0; i < properties.length; i += 1) {
document.writeln(properties[i] + ':' + another_stooge[properties[i]] );
}
删除
delet可以删除对象的属性,但会在索引时读取到来自原型链中的属性
another_stooge.nickname //'Moe'
delete another_stooge.nickname //删除操作
another_stooge.nickname //'Curly' 索引到原型链中的属性值
减少全局变量污染
全局变量削弱了程序的灵活性,所以应该避免。
我们可以通过创建唯一一个全局变量var MYAPP = {}来最小化使用全局变量
MYAPP.stooge = {
"first-name":"Joe",
"last-name":"Howard"
}
通过把多个全局变量整理在一个名称空间下,我们可以降低与其他应用程序、组件或类库之间产生的相互影响的可能性。