JavaScript的简单数据类型包括数字、字符串、布尔值、null值和undefined值,其他所有的值都是对象。数字、字符串、布尔值“貌似”对象,因为他们拥有方法,但是他们是不可变的。
JavaScript中的对象是可变的键控集合。在JavaScript中,数组是对象,函数是对象,正则表达式是对象,当然对象自然也是对象。
对象是属性的容器,其中每个属性都拥有名字和值。属性的名字可以是包括空字符串在内的任意字符串。属性值可以是除了undefined值之外的任何值。
JavaScript的对象是无类型(class-free)的。它对新属性的名字和属性的值没有限制。对象适合用于汇集和管理数据。对象可以包含其他对象,所以它们可以容易地标识成树状或者是图形结构。
JavaScript包含一种原型链的特性,允许对象继承另一个对象的属性。正确地使用它能减少对象初始化时消耗的时间和内存。
JavaScript的对象使用一对花括号中0个或者多个“属性名/属性值”对来表示。属性名是合法的时候并不强制要求使用引号
属性的值可以从包括另一个对象字面量在内的任意表达式中获得。对象是可以嵌套的。
实例
var stoge = { "first-name":"Jerome" } var flight = { airline: "Oceanic", number:815, departure:{ IATA:"SYD", time:"2016-01-01 14:55", city:"Sydney" }, arrival:{ IATA:"LAX", time:"2016-01-02 10:42", city:"Los Angeles" } }
检索Retrieval
要检索对象里面包含的值,有两种方式 [ ]和 . 。[]是在对象后缀中括住一个字符串表达式的方式。如果字符串表达式是一个字符串字面量,而且它是一个合法的JavaScript标识符且不是保留字,那么可以用 . 表示法代替。优先考虑使用 . 表示法,因为它更紧凑且可读性更好。
实例
stoge["first-name"] //返回"Jerome" flight.departure.IATA //返回 "SYD"
如果检索一个不存在的成员属性的值,返回undefined
stoge["middle-name"] //返回undefined
||可以填充默认值
var middle = stoge["middle-name"] || "{none}"; //返回"{none}"
&&可以避免错误(从undefined的属性成员中取值将会导致TypeError异常)
flight.equipment //undefined flight.equipment.model //throw "TypeError" flight.equipment && flight.equipment.model //undefined
更新Update
对象里的值可以通过复制语句来更新。如果属性名已经存在于对象里,那么这个属性的值就会被替换,如果对象之前没有拥有那个属性ing,那么该属性就被扩充到对象当中。
stoge["first-name"] = "liusxg";
引用Reference
对象通过引用来传递,它们永远不会被复制
var x = stoge; x.nickname = ‘Curly‘; var nick = stoge.nickname; //因为x和stoge是指向同一个对象的引用,所以nick为‘Curly‘ var a = {}, b = {}, c = {}; //因为a、b和c每个人都引用一个不同的空对象 a = b = c = {}‘ //a、b和c都引用同一个空对象
原型Prototype
每个对象都连接都一个原型独享,并且它可以从中继承属性。所有通过对象字面量创建的对象都连接到Object.prototype,它是JavaScript中的标配对象。
当你创建一个新对象时,你可以选择某个对象作为它的原型。JavaScript提供的实现机制杂乱而复杂,但其实可以被明显地简化。我们江哥Object增加一个create方法。这个方法创建一个使用元对象作为其原型的新对象。
var another_stoge = Object.create(stoge);
原型连接在更新时是不起作用的。当我们对某个对象作出该表时,是不会触及改对象的原型
another_stoge["first-name"] = ‘Harry‘;
原型连接只有在检索值的时候才被用到。如果我们尝试去获取对象的某个属性值,但该对象没有此属性值,那么再从它的原型中寻找,以此类推,知道该过程最后到达终点Object.prototype。如果想要的属性完全不存在于原型链中,那么结果就是undefined值。这个过程称为委托。
原型关系是一种动态的关系。如果我们添加一个新的属性到原型中,该属性会立即对所有基于该原型创建的对象可见。
stoge.profession = ‘action‘; another_stoge.profession //‘action‘
反射Reflection
检查对象并确定对象有什么属性是很容易的事情,只要试着去检索改属性并验证取得的值。
typeof fight.number //‘number‘ typeof flight.status //‘string‘ typeof flight.manifest //‘undefined‘
请注意原型链中的任何属性都会产生之:
typrof flight.toString //‘function‘ typrof flight.constructor //‘function‘
有两种方法处理掉这些不需要的属性。第一个是让你的程序做检查并丢弃值为函数的属性,一般来说,当你想让对象在运行时动态获取自身信息时,你关注更多的是数据,而你应该意识到到一些值可能会是函数。
另一个方法是使用hasOwnProperty方法,如果对象拥有独有的属性,它将返回true。hasOwnProperty方法不会检查原型链。
flight.hasOwnProperty(‘number‘) //true flight.hasOwnProperty(‘construction‘) //true
枚举Enumeration
for in 语句可用 来遍历一个对象中的所有属性名。该枚举过程将会列出所有的属性--包括函数和你可能不关心的 原型中的属性--所有有必要过滤掉那些你不想要的值。最为常用的过滤器是hasOwnProperty方法,以及使用typeof来排除函数
实例
var name; for (name in another_stoge){ if(typeof another_stoge[name] !== ‘function‘){ document.write(name + ‘: ‘ + another_stoge[name]); } }
属性名出现的顺序是不确定的,因此要对任何可能出现的顺序有所准备。如果你想要确保属性以特定的顺序出现,最好的办法就是不使用for in 语句,而是创建一个数组放置属性名,并以for循环来获取想要的属性值
实例
var i; var properties = [ ‘first-name‘, ‘middle-name‘, ‘profession‘ ]; for (i = 0; i < properties.length; i++){ document.writeln(properties[i] + ‘: ‘ + another_stoge[properties[i]]); }
这可以直接获取我们需要的属性,而不用担心可能发掘出原型链中的属性。
删除Delete
delete运算符可以用来删除对象属性。如果对象包含该属性,那么该属性就会被移除。它不会触及原型链中的任何对象。
删除对象的属性可能会让来自原型链中的属性透现出来,
another_stoge.nicknam //‘Moe‘ //删除another_stoge的nickname属性,从而暴露出原型的nickname属性。 delete another_stoge.nickname; another_stoge.nickname // ‘Curly‘
减少全局变量污染Global Abatement
JavaScript可以很随意地定义全局来容纳你的应用的所有资源。但是全局变量削弱了程序的灵活性。
最小化使用全局变量的方法之一就是为你的应用只创建一个唯一的全局变量
var MYAPP = {};
该变量此时就变成了你应用的容器
MYAPP.stoge = { "first-name":"Joe", "last-name":"Howard" }; MYAPP.flight = { airline: "Oceanic", number:815, departure:{ IATA:"SYD", time:"2016-01-01 14:55", city:"Sydney" }, arrival:{ IATA:"LAX", time:"2016-01-02 10:42", city:"Los Angeles" } };
只要把全局性的资源都纳入一个名称空间之下,你的程序与其他应用程序、组件或者类库之间发生冲突可能性就会显著降低。同时也可以使用闭包来减少全局污染。