《javascript语言精粹》学习笔记 – 对象


Javascirpt里的对象是无类型的。它对新属性的名字和属性的值没有任何的限制。对象适用于汇集和管理数据。对象可以包括其他对象,所以它们可以容易地表示成树状或者图形结构。

对象字面量

创建一个自定义对象最简单的方式就是创建一个Object的实例,然后为它添加属性和方法:

var person = new Object();
    person.name = 'john';
    person.age = 16;
    person.say = function(){
        console.log(this.name + ' ' + this.age);
    };

后来对象字面量成为一个创建这种对象的首选方式。对象字面量提供一种非常方便的创建新对象的表示法。

var Person = {},
    Person2 = {
        name: 'john',
        age: 16,
        say: function(){
            console.log(this.name + ' ' + this.age);
        }
    };

一个对象字面量就是包围在一对花括号({})的多个名/值对。对象字面量可以出现任何允许表达式出现的地方。

属性名可以包括空字符串在内的任何字符。属性名是一个合法的js标示符而且不是保留字的话就不用引号括起来。特殊情况例如:"my-name"这种的话,因为js中的标示符中包含连接符(-)是不合法的,所以要用引号去包住,如果用下划线(_)就不用了。

对象字面量属性值里面可以在嵌套对象的。

var Person = {
    name: 'john',
    Person2: {
        age: 16
    }
};

检索

要检索的对象包含的值,可以采用[]后缀中括住一个字符串表达式方式。也可以用.方法,但是前提要是一个合法的js标示符且不是保留字。

person['name'];
person.name;

如果属性值没有的话,我们可以用||充当默认值。

var name = person['name'] || 'john';

尝试从undefind对象里取值将会导致TypEerror异常。可以通过&&运算符来避免错误。

flight.equipment // undefined
flight.equipment.model // TypeError
flight.equipment && flight.equipment.model// undefined

引用

对象是通过引用来传递的,而不是复制。

// 例子一
var stooge = {},
    x = stooge;
x.nickname = 'john';
var nick = stooge.nickname;
alert(nick); // john

// 例子二
var a = {}, b = {}, c = {};
// a = b = c = {};
  • 例子一的代码因为xstooge是指向同一个对象的引用。
  • 例子二的代码其实abc都引用同一个对象。

更新

对象可以使用赋值语句来更新值。如果属性名已经存在的话,就回去被替换掉。如果值不存在,就扩充到对象中。

var person = {
    name: 'Ada'
}
person.name = 'john'; // john
person.age = 16 // 16

原型

每个对象都能连接到一个原型对象,并且它可以从中继承属性。

当你创建一个新的对象的时候,你可以有选择性的某个对象作为它的原型。js给我们的机制是很复杂的,但是可以被明显的简化,来给Object添加一个create方法。

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

注意:原型连接在更新时是不会起作用的。当对某个对象做出改变的时候,不会触及该对象的原型。

原型链接只有在检索值的时候才会用到。如果我们尝试去获取对象的某个值的时候,如果对象没有该属性名,那么js会尝试去原型对象中获取属性值。如果那个原型也没有的话,就会一直从它的原型里面找。如果最后还是找不到的话机会返回一个undfined。这个过程称为委托

原型关系是一种动态的关系。如果添加到一个新的属性值到原型中,该属性会立即对所有基于这个原型创建的对象可见。

反射

检查对象并且确定对象有什么属性是一件很容易的事情,只要尝试的去检索那个属性并且验证取得的值。使用typeof来对确定属性的类型。

var person = {
    name: 'john',
    age: 16,
    say: function(){
        console.log(this.name + ' - ' + this.age);
    }
};
alert(typeof person.name); // string
alert(typeof person.age); // number
alert(typeof person.say); // function

另外一种方法是使用hasOwnProperty方法,如果对象拥有独有的属性值,它将会放回true。注意:hasOwnProperty方法不会检查原型链。

alert(person.hasOwnProperty('name')); // true
alert(person.hasOwnProperty('sex')); // false

枚举

for in循环可以用来遍历一个对象中的说有属性名。
注意:使用for in循环过程中也会列出那些你不关心的原型中的属性,如果想要过滤掉那些你不需要的值。你可以使用hasOwnProperty方法,以及typeof来排除函数。

for (var name in person) {
    if (typeof person[name] !== 'function') {
        alert(person[name]);
    }
};

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

var i = 0,
    properties = [
        'name',
        'age'
    ];
for (; i < properties.length; i++) {
    alert(person[properties[i]]);
};

通过使用for循环而不是for in循环,就可以得到想要的值,也不用担心可能发掘出原型链中的属性。

删除

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

var Person = function(name, age){
    this.name = name;
    this.age = age;
};
Person.prototype.name = 'Ada';

var person = new Person('john', 16);

alert(person.name); // john
delete person.name;
alert(person.name); // Ada

删除对象的属性可能会让来自原型链中的属性透现出来。

严格模式下,不能用delete 删除显式声明的标识符,名称或具名函数。

减少全局变量污染

js可以很随意去定义全局变量来容纳你的应用的所有的资源。不好的是,全局变量削弱了程序的灵活性,应该都要避免使用。

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

var MyApp = {};

这个变量就会成为你的应用的容器了。

MyApp.person = {
    name: 'john',
    age: 16
};

MyApp.person2 = {
    name: 'Age',
    age: 14,
    sayName: function(){
        alert('name: ' + this.name);
    }
};

只要把全局性的资源都纳入一个名称空间下,自己写的程序与其他的程序、组件或者类库之间发生的冲突就会大大的减少。自己写的程序也会变得更加容易的阅读。还有另外一种方法也是可以有效的减少全局污染,那就是闭包


One response on “《javascript语言精粹》学习笔记 – 对象

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>