ECMAScript5 Object新增的方法
系统的学习Object新增的方法,可以让我们能够更加灵活地使用Object,当然IE版本必须满足9或以上。
Object.create(prototype, descriptors)
以指定的原型创建对象,并且可以(可选)的设置对象的属性。
function Person(name, age) {
this.name = name;
this.age = age;
}
var people = Object.create(new Person('Li', 23));
Person.constructor; // function Function() { \[native code\] }
new Person().constructor; // function Person(name, age) {
// this.name = name;
// this.age = age;
// }
Person.constructor.prototype; // function () {}
Person.prototype == new Person().constructor.prototype; // true
Person.constructor.prototype == new Person().constructor.prototype; // false
Person.prototype == people.constructor.prototype; // true
Person.constructor.prototype == people.constructor.prototype; // false
people.age // 23
people.name // 'Li'
其实,Object.create构造的对象和用构造函数构造的对象在结果上没有什么差异。用Object.create的好处是原型链干净,网上有有给出了以下没有Object.create的浏览器的解决同样解决方案。以下代码不但说明了Object.create的技术内幕,同时可以支持低版本的IE同样可以实现干净的原型。
if (typeof Object.create !== 'function') {
Object.create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}
当然,为了得到一个原型链上没有任何属性或方法的对象,我们可以使用这种方法:
var obj = Object.create(null);
obj.toString() // Uncaught TypeError: obj.toString is not a function
obj.prototype // undefined
Object.defineProperty(object, propertyname, descriptor)
将属性添加到对象,或修改现有属性的特性。第一个参数是要操作的对象,第二参数是操作的字段,第三参数是取值。
var obj = {};
Object.defineProperty(obj, 'a', {
value: 11
});
console.log(obj.a); // 11
看上去和直接给obj.a = 11差不多,但是这只是表面上而已。value只是descriptor中的一种值。descriptor的值有:
- value 属性的值,默认undefined
- writable 表示属性是否可修改,默认是false
- configurable 表示能否通过delete删除属性而重新定义,能否修改属性的特性,能否把属性修改为访问器熟属性,默认是false
- enumerable 表示是否可通过for-in或Object.keys()枚举,默认false
- get 访问器属性(见下文)
- set 访问器属性(见下文)
对于刚才的操作(第一次设置时),其实相当于这样:
Object.defineProperty(obj, 'a', {
value: 11,
configurable: false,
writable: false,
enumerable: false
});
configurable像是总开关,当被设置成false时,将无法再次调用该函数。如:
var obj = {};
Object.defineProperty(obj, 'a', {
value: 11,
configurable: false
});
Object.defineProperty(obj, 'a', { // Uncaught TypeError: Cannot redefine property: a
configurable: true
});
当writable被设置成false时,我们仍给变量复制时,并不会报错,但值不会被修改。
var obj = {};
Object.defineProperty(obj, 'a', {
value: 11,
writable: false
});
obj.a = 11111; // 不会报错
console.log(obj.a); // 11
enumerable就是枚举使用,不在举例。
get、set访问器属性
在 descriptor 中不能同时设置访问器 (get 和 set) 和 writable或 value,否则会错。
var obj = {};
Object.defineProperty(obj, 'a', {
get: function() {
console.log('get');
},
set: function(value) {
console.log('set ' + value);
},
enumerable: true,
configurable: true
});
obj.a = 11; // set 11
obj.a; // get
Object.defineProperties(object, descriptors)
该方法和前一个方法的用法是一样的,不同的就是该方法可以一次添加多个属性。其他用法同前一个函数。
var obj = {};
Object.defineProperties(obj, {
'a': {
value: 11
},
'b': {
get: function() {
alert();
},
set: function() {
alert();
}
}
});
Object.getOwnPropertyDescriptor(object, propertyname)
用于获取对象已经被定义的属性。
var obj = {};
Object.defineProperty(obj, 'a', {
configurable: true,
enumerable: true,
writable: true,
value: 12
});
var descriptor = Object.getOwnPropertyDescriptor(obj, 'a');
console.log(descriptor); // Object {value: 12, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyNames(object)
返回所有属性的名称,哪怕说是不能枚举的属性。
var obj = {};
Object.defineProperty(obj, 'a', {
configurable: false,
enumerable: false,
writable: false,
value: 12
});
var values = Object.getOwnPropertyNames(obj);
for (var i = 0; i < values.length; ++i) {
console.log(Object.getOwnPropertyDescriptor(obj, values\[i\]));
// Object {value: 12, writable: false, enumerable: false, configurable: false}
}
Object.preventExtensions(object)
可以阻止对象添加新的属性,但属性的值可以改,也可以删除。
var obj = {
'a': 1,
'b': 2
};
Object.preventExtensions(obj);
obj.c = 3;
console.log(obj); // Object {a: 1, b: 2}
Object.isExtensible(object)
对象是否可以添加属性。
var obj = {};
var obj1 = {};
var obj2 = {};
Object.preventExtensions(obj);
console.log(Object.isExtensible(obj)); // false
console.log(Object.isExtensible(obj1)); // true
console.log(Object.isExtensible(obj2)); // true
Object.seal(object)
对象不能添加和删除属性。
var obj = {
'a': 1,
'b': 2
};
Object.seal(obj);
delete obj.a;
obj.c = 3;
console.log(obj); // Object {a: 1, b: 2}
Object.isSealed(object)
对象是否不能添加和删除属性。
Object.freeze(object)
防止现有属性和属性值的修改,并防止新特性的添加。
var obj = {
'a': 1,
'b': 2
};
Object.freeze(obj);
delete obj.a;
obj.c = 3;
obj.b = 222;
console.log(obj); // Object {a: 1, b: 2}
Object.isFrozen(object)
对象是否freeze了。
Object.getPrototypeOf(object)
用于得到对象的原型。
var obj = {
'a': 1,
'b': 2
};
console.log(Object.getPrototypeOf(obj)); //Object {}
var obj = Object.create(null);
console.log(Object.getPrototypeOf(obj)); // null
ObjectA.isPrototypeOf(ObjectB)
判断B是否是A派生的一个实例
var o = {
'a': 1
};
var obj = Object.create(o);
console.log(o.isPrototypeOf(obj)); // true
Object.hasOwnProperty()
判断属性是否存在于对象的实例中,与in不同,不会检索原型上的属性。
var o = {
'a': 1
};
var obj = Object.create(o);
obj.b = 2;
console.log(obj.hasOwnProperty('b')); // true
console.log(obj.hasOwnProperty('a')); // false
Object.keys()
遍历实例对象的属性,与in不同,不会遍历原型上的属性,返回一个数组,包含所有的属性名。
var o = {
'a': 1
};
var obj = Object.create(o);
obj.b = 2;
obj.c = 3;
console.log(Object.keys(obj)); // \["b", "c"\]