您的位置:首页 > Web前端 > JavaScript

《JavaScript语言精粹》学习笔记(对象)

2017-04-10 17:25 369 查看

第三章 对象(Objects)

JavaScript的简单数据类型包括数字、字符串、布尔值、null和undefined。其他所有的值都是对象。JavaScript中对象是可变的键控集合(Keyed collections)。

对象是属性的容器,其中每个属性都拥有名字和值。

JavaScript里的对象是无类型的,它对新属性的名字和属性的值是没有要求(限制)的。

JavaScript包含一种原型链的特性。允许对象继承另一个对象的属性。

1.对象字面量(Object Literal)

一个字面量就是包含在一对花括号中的零或多个“名/值”对。

var empty_object = {};
var me = {
"first-name": "Dong",
"last-name": "Xiao"
};


属性的值可以从包括另一个对象字面量在内的任意表达式中获得。对象是可以嵌套的:

var flight = {
airline: "H-S",
number: 001,
departure:{
time: "2017-4-10 17:18",
city: "HangZhou"
},
arrival:{
time: "2017-4-10 17:28",
city: "Shanghai"
}
};


2.检索(Retrieval)

要检索对象里的值,可以在对象名后跟上一个[],其中包括一个属性名的字符串表达式。如果字符串的表达式是一个字符串字面量,且它是一个合法的标识符而不是保留字,那么也可以用 . 表示法代替。

me["first-name"]           //"Dong"
flight.arrival.city        //"Shanghai"


如果尝试检索一个不存在的属性值,将会返回undefined。

尝试从undefined的成员属性中取值会造成TypeError异常。可以通过&&运算符避免异常。

flight.plane                         //undefined
flight.plane.type                    //throw "TypeError"
flight.plane.type && flight.plane    //undefined


3.更新(Update)

对象里的值可以通过赋值语句来更新。如果属性名已经存在于对象中,那么该属性对的值会被替换;如果属性名还不存在,那么该属性就会被添加到对象中。

4.引用(Reference)

对象通过引用来传递。它们永远不会被复制:

var x = me;
x.nickname = "xiaoxiao";
var nick = me.nickname; // "xiaoxiao"
//因为x和me是同一个对象的引用,所以nick的值是"xiaoxiao"
var a = {}, b = {}, c = {};
//a,b,c都引用了不同的空对象
a = b = c = {};
//a,b,c引用了同一个空对象


5.原型(Prototype)

每个对象都连接到一个原型对象Object.prototype,所有通过对象字面量创建的对象都连接到它,并可以从中继承属性。

在本书中,作者提供了一个简化的对象继承原型的方法create(创建一个使用原对象作为其原型的新对象):

if (typeof Object.beget !== 'function') {
Object.create = function(o) {
var F = function() {};
F.prototype =o;
return new F();
};
}
var another_me = Object.create(me);


原型连接只有在更新时时不起作用的。当我们对某个对象做出改变的时候,不会触及原型:

another_me["first-name"] = 'Zou';
another_me["last-name"] = 'Jingqi';
another_me.nickname = 'honey';


原型连接只有在检索值的时候才会被用到。如果我们尝试去获取对象a的某个属性值,而该对象a没有这个属性值,那么JavaScript会试着从这个对象的原型对象b中获取属性值。若对象b也没有这个属性值,那么再从b的原型对象中寻找。以此类推,直到寻找到Object.prototype。如果整个原型链中都不存在这个属性值,那么结果就会返回undefined。这个过程被称为 委托。

原型关系是一种动态关系。如果添加一个新属性到原型中,那么这个属性会运用于所有基于该原型创建的对象。

me.profession = 'student';
another_me.profession      //'me'


6.反射(Reflection)

检查对象并确认对象有什么属性是很容易的事情,只要试着去检索该属性并验证获得的值。

typeof操作符对检查属性的类型很有帮助:

typeof flight.number      //'number'
typeof flight.airline     //'string'
typeof flight.arrival     //'object'
typeof flight.manifest    //'undefined'


注意原型链中的任何属性都会产生值:

typeof flight.toString    //'function'
typeof flight.constructor //'function'


有两种方法去处理这些不需要的属性。第一是让你的程序做检查并丢弃值为函数的属性;第二是使用hasOwnProperty方法,如果对象拥有独立的属性,它将返回true,这个方法不会检查原型链:

flight.hasOwnProperty('number')      // true
flight.hasOwnProperty('constructor') // false


7.枚举(Enumeration)

for in 语句可以用来遍历一个对象中的所有属性名。该枚举过程会列出所有的属性——包括函数和你不需要的原型中的属性——所以需要过滤掉那些你不想要的值,最为常用的过滤器是hasOwnProperty方法,以及使用typeof来排除函数:

var name;
for (name in another_me){
if (typeof another_me[name] !== 'function') {
document.writeln(name + ':' + another_me[name]);
}
}


属性名的出现顺序是不确定的,因此要对任何可能出现的顺序有所准备。如果想要确保属性以正确的顺序出现,最好的办法就是避免使用for in 语句,而是创建一个数组,在这个数组中用正确的顺序包含属性名:

var i;
var properties = [
'first-name',
'last-name',
'profession'
];
for (i = 0; i < properties.length; i += 1) {
document.writeln(properties[i] + ':' +
another_me[properties[i]]);
}


通过使用for ,可以得到想要的属性,并且不用担心可能检索到原型链中的属性,而且我们按正确的顺序取得了它们的值。

8.删除(Delete)

delete运算符可以删除对象的属性。如果这个对象包含该属性,那么该属性会被移除。它不会涉及原型链中的任何对象。

删除对象可能会让原型链中的对象属性显现出来:

another_me.nickname      //'honey'
//删除 another_me 的nickname 属性,从而暴露出原型的nickname属性。
delete another_me.nickname;
another_me.nickname      //'xiaoxiao'


9.减少全局变量污染(Global Abatement)

JavaScript可以很随意地定义全局变量来容纳应用中的所有资源。但是全局变量削弱了程序的灵活性,应该避免使用。

最小化使用全局变量的方法之一是为你的应用只创建一个唯一的全局变量:

var myApp = {};


该变量此时变成了你应用的容器:

myApp.me = {
"first-name": "Dong",
"last-name": "Zhengxiao"
};

myApp.flight = {
airline: "S-W",
number: 429,
departure:{
time: "2017-4-29",
city: "Shanghai"
},
arrival:{
time: "2017-4-29",
city: "Wuxi"
}
};


只要把全局性的资源都纳入一个名称空间下,你的程序与其他应用程序、组件或类库的冲突可能性就会显著降低。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript