第3章-对象
JavaScript的简单数据类型包括数字、字符串、布尔值、null和underfined值。其他所有值都是对象。对象是属性的容器,其中每个属性都有名字和值。属性的名字可以是包括空字符串在内的任意字符串。属性值可以是除underfined值之外的任何值
对象字面量 Object Literals
对象字面量提供了一种非常方便地创建新对象值的方法。一个对象字面量就是包围在一堆花括号中的零个或多个“名/值”对。
1 var empty_object = {}; 2 3 var stooge = { 4 "first-name" : "Jerome", 5 "last-name" : "Howard" 6 };
属性名可以是包含空字符串在内的任何字符串。在对象字面量中,如果属性名是一个合法的JavaScript标识符且不是保留字,则并不强制要求用引号括住属性名。所以用引号括住“first-name”是必须的,但“first_name”则书可选的(JavaScript的标识符中包含连接符 - 是不合法的,但允许下划线 _ )
对象是可以嵌套的
1 var flight = { 2 airline : "Oceanic", 3 number : 849, 4 departure: { 5 IATA :"SYD", 6 time : "2004-02-11", 7 city :"Gan Su" 8 }, 9 };
检索 Retrieval
要检索对象里包含的值,可以使用[]括住一个字符串表达式的方式。如果表达式是一个字符串字面量,而且它是一个合法的JavaScript标识符且不是保留字,那么也可以采用.表示法
1 stooge["first-name"] //""Jerome""
检索一个不存在的值,返回underfined
1 stooge["middle-name"] //"undefined"
|| 运算符可以用来填充默认值
1 var middle = stooge["middle-name"] || "(none)"; 2 var status = flight.status || "unknown";
尝试从underfined的成员属性中取值将会导致TypeError异常,可以通过&&运算符来避免错误。
1 flight.equipment //undefined 2 flight.equipment.model //TypeError 3 flight.equipment && flight.equipment.model //undefined
更新 Update
对象里的值可以通过赋值语句来更新,如果之前没有那个属性,那么该属性就会被添加到对象中
引用 Reference
对象通过引用来传递,他们永远不会被复制
1 var x = stooge; 2 x.nickname = "City"; 3 var nick = x.nickname; 4 因为x和stooge是指向同一个对象的引用,所以nick为"City" 5 6 var a = {},b = {},c = {}; 7 //a,b,c都引用一个不同的空对象 8 9 var a = b = c = {}; 10 //a,b,c都引用同一个空对象
原型 Prototype
每个对象都链接到一个原型对象,并且它可以从中继承属性。所有通过对象字面量创建的对象都链接到Object.prototype,它是JavaScript中的标配对象。
给Object增加一个create方法,这个方法创建一个使用原对象作为其原型的新对象
1 if(typeof Object.beget !== 'function'){ 2 Object.create = function(o){ 3 var F = function(){}; 4 F.prototype = o; 5 return new F(); 6 }; 7 } 8 9 var another_stooge = Object.create(stooge);
原型链在更新时是不起作用的,当我们对某个对象做出改变时,不会触及该对象的原型
原型链只有在检索值的时候才能被用到,如果去检索某个对象的某个属性值,但该对象没有这个属性值,则就向它的原型链对象中检索这个属性。
如果我们添加一个新的属性到原型中,那么基于该原型的所有对象都会有这个属性
反射 Reflection
检查对象并确定对象有什么属性是很容易的事情,原型链中的任何属性都会产生值:
1 var flight = { 2 airline : "Oceanic", 3 number : 849, 4 departure: { 5 IATA :"SYD", 6 time : "2004-02-11", 7 city :"Gan Su" 8 }, 9 }; 10 typeof flight.toString //'function' 11 typeof flight.number //'number'
有两种方法可以处理掉不需要的属性,第一个是让你的程序做检查并丢弃值为函数的属性,第二种方法是使用hasOwnProperty方法,如果对象拥有独有的属性,他将返回true
1 flight.hasOwnProperty('number') //true 2 flight.hasOwnProperty('constructor') //false
枚举 Enumeration
for in 语句可以用来遍历一个对象中的所有属性,但是该枚举过程会列举出所有的属性,包括你不希望的原型中的属性。要过滤这些不想要的值最常用的过滤器是hasOwnProperty方法,以及使用typeof来排除函数
1 var name; 2 for(name in another_stooge){ 3 if(typeof another_stooge[name] !== 'function'){ 4 document.writeln(name + ': ' + another_stooge[name]); 5 } 6 }
以上方法属性名出现的顺序是不确定的,如果你想要的属性一特定的顺序出现,最好是创建一个数组,在其中以正确的顺序包含属性名:
1 var i; 2 var properties = { 3 'first-name', 4 'middle-name', 5 'last-name', 6 'profession' 7 }; 8 for(i=0;i<properties.length;i++){ 9 document.writeln(properties[i] + ': ' + another_stooge[properties[i]]); 10 }
删除 Delete
delete运算符可以用来删除对象的属性,他不会触及原型链中的任何对象,删除对象的属性可能会让来自原型链中的属性透出来
减少全局变量污染 Global Abatement
最小化使用全局变量的方法之一就是为你的应用值添加一个全局变量:
1 var MAYPP = {};
该变量此时变成了你的容器:
1 MYAPP.stooge = { 2 'first-name' : 'Joe', 3 'last-name' : 'Howard' 4 }; 5 MYAPP.flight = { 6 airline : "Oceanic", 7 number : 849, 8 departure: { 9 IATA :"SYD", 10 time : "2004-02-11", 11 city :"Gan Su" 12 };
只要把全局性的资源都纳入一个名称空间下,你的程序与其他应用程序、组件或类库之间发生冲突的可能性就会显著降低。