JavaScript简单数据类型包括数字、字符串、布尔值、null值和undefined值,其他所有的值都是对象。
对象是属性的容器,其中每个属性都有名字和值。属性的名字可以是包括空字符串在内的任意字符串。属性值可以是除undefined值之外的任何值。
JavaScript里的对象是无类型的。对新属性的名字和属性的值没有限制。对象适用于汇集和管理数据。
JavaScript包含一种原型链的特性,允许对象继承另一个对象的属性。正确使用它能减少对象初始化时消耗的时间和内存。
一、对象字面量
一个对象字面量就是包围在一对花括号中的零或多个“名/值”对。
var empty_object = {}; //这是一个空的对象
var stooge = {
"first-name" : "Jerome",
"last-name" : "Howard"
}
属性名可以是包括空字符串在内的任何字符串。如果属性名是一个合法的JavaScript标识符且不是保留字,则不强制要求用引号括住属性名。所以用引号括住"first-name"是必需的,但是括住first_name是可选的。
逗号用于分隔多个“名/值”对。
属性值可以从包括另外一个对象字面量在内的任意表达式中获得。也就是对象可以嵌套的。例如:
var flight = {
airline: "Oceanic",
number: 815,
departure: {
TATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: {
TATA: "LAX",
time: "2004-09-23 10:42",
city: "Los Angeles"
}
}
二、检索
检索对象里包含的值,可以采用[]后缀中括住一个字符串表达式的方式。如果字符串表达式也是一个字面量,而且是合法的JavaScript标识符且不是保留字,那么也可以使用.表示法代替。优先考虑 . 表示法。
console.log(stooge["first-name"]); //"Jerome"
console.log(flight.departure.TATA); //"SYD"
如果检索一个并不存在的成员属性,将返回undefined。
console.log(stooge["minddle-name"]); //undefined
console.log(flight.status); //undefined
console.log(stooge["FIRST-NAME"]); //undefined
可以利用 || 运算符来填充默认值。
var middle = stooge["middle-name"] || "(none)";
console.log(middle); //"(none)"
var status = flight.status || "unknow";
console.log(status); //"unknow"
尝试从undefined的成员属性中取值将会导致TypeError异常,这是可以通过&&运算符来避免错误。
console.log(flight.equipment); //undefined
console.log(flight.equipment.model); //throw "TypeError"
console.log(flight.equipment && flight.equipment.model); //undefined
三、更新
对象里的值可以通过赋值语句来更新。如果属性名已经存在于对象里,那么这个属性的值就会被替换。
stooge['first-name'] = 'Jerome';
console.log(stooge['first-name']); //"Jerome"
如果对象之前没有拥有那个属性名,那么该属性就被扩充到对象中。
stooge['middle-name'] = 'Lester';
stooge.nickname = 'Curly';
flight.equipment = {
model: 'Boeing 777'
};
flight.status = 'overdue';
console.log(stooge);
console.log(flight);
四、引用
对象通过引用来传递,所以它们永远不被复制
var x = stooge;
x.nikename = 'Curly';
var nick = stooge.nickname;
console.log(x === nick); //true
//因为x和stooge是指向同一个对象的引用,所以nick为'Curly'
var a = {}, b = {}, c = {};
console.log(a === b === c); //false
//a、b和c每个都引用不同的空对象
var a1 = b1 = c1 = {};
console.log(a1 === b1 === c1); //true
//a、b和c都引用同一个空对象
五、原型
每个对象都连接到一个原型对象,并且它可以从中继承属性。所有通过对象字面量创建的对象都连接到object.prototype,它是JavaScript中的标配对象。
创建一个新对象时,可以选择某个对象作为它的原型。给object增加一个create方法。这个方法创建一个使用原对象作为其原型的新对象。
console.log(stooge);
if (typeof Object.beget !== 'function') {
Object.creat = function(o) {
var F = function() {};
F.prototype = o; //往原型链上添加数据
return new F();
}
}
var another_stooge = Object.creat(stooge);
console.log(another_stooge);
原型连接在更新时是不起作用的。当我们对某个对象做出改变时,不会触及该对象的原型
another_stooge['first-name'] = 'Harry';
another_stooge['middle-name'] = 'Moses';
another_stooge.nickname = 'Moe';
console.log(another_stooge);
原型链只有在检索时才被用到。如果我们尝试去获取对象的某个属性值,但该对象没有此属性值,那JavaScript会试着从原型对象上获取属性。如果原型对象上也没有就去它的原型中找,以此类推,一直到达终点object.prototype。如果该属性完全不存在于原型链中,那么结果是undefined。这个过程称之为委托。
原型关系是一种动态的关系。如果我们添加一个新的属性到原型链中,该属性会立即对所有基于该原型创建的对象可见。
stooge.profession = 'actor';
console.log(another_stooge.profession); //'actor'
六、反射
可以使用typeof确定属性的类型
console.log(typeof(flight.number)); //number
console.log(typeof(flight.status)); //string
console.log(typeof(flight.arrival)); //object
console.log(typeof(flight.manifest)); //undefined
原型链中的任何属性都会产生值
console.log(typeof(flight.toString)); //function
console.log(typeof(flight.constructor)); //function
有两种方法可以去掉不需要的属性:
第一个是遍历程序并丢弃掉类型为函数的属性
第二个是使用hasOwnProperty方法,如果对象拥有独有的属性,返回true。该方法不会检查原型链
console.log(flight.hasOwnProperty('number')); //true
console.log(flight.hasOwnProperty('constructor')); //false
七、枚举
for in 语句用来遍历一个对象中的所有属性名。配合过滤器hasOwnProperty方法和typeof排除函数。
var name;
for(name in another_stooge) {
if(typeof another_stooge[name] !== 'funtion'){
console.log(name + ':' + another_stooge[name]);
}
}
属性名出现的顺序是不确定的。如果想要确保属性以特定的顺序出现,最好的方法就是完全避免使用for in语句,创建一个数组,以正确的顺序包含属性名:
var i;
var properties = [
'first-name',
'middle-name',
'last-name',
'profession'
];
for(i = 0; i <properties.length; i++) {
console.log(properties[i] + ':' +
another_stooge[properties[i]]
);
}
该方法可以得到我们想要的属性,且不用担心可能发掘出原型链中的属性。
八、删除
delete运算符可以用来删除对象的属性。它不会触及原型链中的任何对象。
删除对象的属性可能会让来自原型链中的属性透现出来:
console.log(another_stooge.nickname); //'Moe'
delete another_stooge.nickname;
//删除another_stooge的nickname属性,从而暴露出原型的nickname属性
console.log(another_stooge.nickname); //'Curly'
九、减少全局变量污染
JavaScript可以随意定义全局变量容纳你应用的所有资源。但是全局变量削弱了程序的灵活性,应该避免使用。
最小化使用全局变量的方法之一是为你的应用只创建一个唯一的全局变量:
var MYAPP = {};
该变量此时就变成了你的应用的容器:
MYAPP.stooge = {
"first-name": "Joe",
"last-name": "Howard"
};
MYAPP.flight = {
airline: "Oceanic",
number: 815,
departure: {
TATA: "SYD",
time: "2004-09-22 14:55",
city: "Sydney"
},
arrival: {
TATA: "LAX",
time: "2004-09-23 10:42",
city: "Los Angeles"
}
};