JavaScript 对象的概述
最简单的概述:在JavaScript中对象仅仅是属性的容器。
每个对象都可以有零个或多个属性值, 这些属性持有一个基本类型的值,也可以是持有一个对象引用。
JavaScript中创建对象的常见方法
JavaScript中常见的常见对象的方式有三种:
. 使用对象字面量 var obj = {}
. 使用new运算符 var obj = new Object()
. 使用create()函数 var obj = Object.create(null);
这三种创建对象的方式的区别在与对象初始化的方式。具体参考后面的文章。
修饰对象
我们可以通过属性描述符来对对象进行修饰。具体可以进行的修饰方法有:
1. 可配置特性(** configurable **)
当这个属性描述符的值为: true 时, 属性可以从父对象中删除,未来还可以修改属性的描述符;
当这个属性描述符的值为: false 时,属性的描述符将被锁定,未来将不可以进行修改. e.g:
``` JavaScript
var person = {};
// 人的性别是不可以修改的 (我们这里只考虑正常情况)
Object.defineProperty(person, "gender", {
configurable : false,
value : 'male'
});
// 人的名字是可以被修改的
Object.defineProperty(person, "name", {
configurable : true,
value : 'Sereno'
});
delete person.gender;
console.log(person.gender); // => male
delete person.name
console.log(person.name); // => undefined
Object.defineProperty(person, "gender", {
configurable : true,
value : 'female'
}); => Uncaught TypeError: Cannot redefine property: gender
person.gender = 'female'; // 这里的修改将不会被正确执行,在严格模式下将抛出错误
console.log(person.log); // =>male
```
这一修饰符主要用于保护对象不被修改,这时一种防御型编程的形式,使得我们自己定义的对象对外表现和语言内置对象表现一样。
2. 可枚举特性(** enumerable **)
当这个属性修饰符的值为: true 时, 这个属性是可以被遍历的。
当这个属性修饰符的值为: false时, 这个属性是不可以被遍历的。e.g:
``` JavaScript
var person = {};
Object.defineProperty(person, "secret", {
confingurable : true,
enumerable : false,
value : 'Just Nothing tell u !'
});
Object.defineProperty(person, "notify", {
configurable : true,
enumerable : true,
value : "It's New Time !"
});
for (var prop in person) {
console.log(prop );
} // => notify
console.log(Object.keys(person)); // => [notify]
console.log(Object.getOwnPropertyNames(person)); // => ['secret', 'notify']
console.log(Object.propertyIsEnumerable('secret')); // => false
```
注意: 这里只是在遍历中隐藏该属性,而不是将属性完全隐藏起来不能访问,我们依然可以使用 . 或 [] 运算符引用该属性。
3. 可写特性(** writable **)
当这个属性修饰符的值为: true 时,与这个属性关联的值是可以改变的。
当这个属性修饰符的值为: false时,与这个属性关联的值是不可以被改变的。e.g:
``` JavaScript
var person = {};
Object.defineProperty(person, 'gender', {
writable : false,
value : 'male'
});
person.gender = 'female';
console.log(perosn.gender); // male
```
检查对象
使用对象检查的方式,我们可以获取得到对象属性的修饰符的值
1. Object.getOwnPropertyDescriptor
通过该方法,可以获取对象属性特性的配置。
```JavaScript
var obj = {prop : 'prop1'};
Object.getOwnPropertyDescriptor(obj, 'prop'); // => Object {value: "prop1", writable: true, enumerable: true, configurable: true}
```
2. Object.getOwnPropertyNames
通过该方法,可以返回对象的全部属性的名字,包括enumerable属性修饰符的值为 false 的属性也能被返回。
``` JavaScript
var obj = Object.create({}, {
innerFunc : {
enumerable : false,
value : function () {
}
},
demo : {
enumerable : true,
value : 12
}
});
console.log(Object.getOwnPropertyNames(obj)); // => ["innerFunc", "demo"]
```
3.Object.hasOwnProperty
JavaScript中,我们在遍历对象的属性时,往往只需要获取对象自身特有的属性即可,而不需要获取对象原型链上的属性。
这时我们需要使用 Object.hasOwnProperty 来帮助我们甄别属性是属于原型链还是对象自身。(这里不再列举演示代码了)。
4. Object.keys
返回对象中可以枚举的属性。
* 更多的对象检查方法请参考 ECMAScript-262 规范中对 Object 对象的定义 *
修改对象
前面两点主要是针对对象的结构入手,这一小节主要是针对对象整体特性来讨论。
1. 冻结对象(** Object.freeze() **)
冻结对象可以有效的防止对象被再次改变。被冻结的对象不能在添加新的属性,已有的属性也不能被移除,已有属性的值也不可被更改。
``` JavaScript
var obj = {
demo : 'demo',
arr : [12, 13, 14]
}
console.log(Object.isFrozen(obj)); // => false
Object.freeze(obj);
console.log(Object.isFrozen(obj)); // => true
delete obj.demo; // 在使用 ' use strict' 声明的时候,将抛出错误
console.log(obj.demo); // => demo
obj.demo = 'newDemo';
console.log(obj.demo); // => demo
obj.newProp = 'prop';
console.log(obj.newProp); // => undefined
```
2. 密封对象(** Obejct.seal **)
密封对象比冻结对象更加严格, 具体这里不再演示和详述,因为实际使用时大部分情境采用冻结对象就足够了,
如果有使用密封对象的需求,可以参见 ECMAScript 规范。
* 更多的对象修改方法请参考 ECMAScript-262 规范中对 Object 对象的定义 *
对象方法借用
当我们需要在一个A对象中使用别的对象的方法,而且同时想要该方法在外界看来就像是A对象自己的方法一样时,
我们可以通过 ** call() ** 和 ** apply() ** 函数来实现。
这两个函数的行为非常的相似,区别在与:
call 函数接受一个参数列表, apply 函数接受一个参数数组。
这两个函数都可以有效的帮助我们使用临时函数来扩充对象的空能。
具体的使用这里限于篇幅,不再进行代码演示。 关于这两个方法的详细介绍将在另一篇文章中叙述。
创建对象
请记住: ** JavaScript中除了 null 和 undefined 之外的一切都被当做对象! **
你是不是怀疑这句话的正确性?你是不是想问JavaScript数字 1 也是对象吗?
我可以明确的告诉你:
* 不用怀疑!!! 数字 1 在JavaScript中也是对象。你试试采用 (1).toString() 或是 1..toString() *
之所以 1.toString() 或获得错误,是因为JavaScript解释器在解释时,认为 . 后面可能是小数,JavaScript中没有整数和浮点数的区别。
记住了吗???
1. 创建对象方法 -- 对象字面量
``` JavaScript
var obj = {
demo : 'demo',
func : function (){
}
};
```
对象字面量可以直观的反映出对象的内部结构,方便快速创建一个特定对象。
区别于:new Object() 和 Object.create() 语法,字面量语法不会被显示调用,因为在特定的上下文中,字面量实际上使用的是:
Object.create() 方法的快捷方式。对象字面量语法创建的对象,没有显式的构造函数,这也意味着字面量对象不能作为对象工厂。
对象字面量也是实现* 单例 * 设计模式的常用手段。
2. new Object()
这里可能直接讨论 new 运算符大家更容易明白该语法具体都做了些什么:
当我们采用 new 运算符实例化一个对象时,JavaScript实际上做了一下4个步骤:
1): JavaScript创建一个新的空对象 -- 相当于创建了一个对象字面量{}
2): JavaScript将新创建的这个空对象的构造函数链接到类上。
3): JavaScript将新创建的这个对象的原型链接到类的原型上。
4): JavaScript将传入的参数赋给新创建的对象。
3. Object.create()
这一个方法时在ECMAScript 5 中引入的,Obejct.create() 方法可以接受两个参数:一个是提供原型的对象,另一个是可选属性的对象,
这个对象包含新创建对象的配置。
``` JavaScript
var obj = {
func : function (num) {
return num;
}
}
var person = Object.create(obj, {
'demo' : {
prop : 'pro',
arr : [1, 3, 5, 7, 9]
}
});
console.log(person.func(test)); // => test
```
* 更多的关于对象创建的讨论,请参见大神 NicholasC.Zakas 的《JavaScript高级程序设计》(第三版) *