一、Object对象
JavaScript 原生提供Object对象(注意起首的O是大写),本章介绍该对象原生的各种方法。
JavaScript 的所有其他对象都继承自Object对象,即那些对象都是Object的实例。
1. Object对象的作用
- 判断一个变量是否为对象,因为Object()会将传入的参数包装为一个对象,如果变量没有发生变化那么就说明该变量为对象,如果发生变化就说明该变量不是对象。
function isObject(value) {
return value === Object(value);
}
isObject([]) // true
isObject(true) // false
- 可以被当做构造函数使用,如果接受的参数为一个对象,那么直接返回该对象,如果接收到的是一个原始类型的值,那么就返回一个包装对象。
var o1 = {a: 1};
var o2 = new Object(o1);
o1 === o2 // true
var obj = new Object(123);
obj instanceof Number // true
2. Object.keys 和 Object.getOwnPropertyNames的区别
Object.getOwnPropertyNames 可返回对象的不可枚举对象,而Object.keys只能返回可枚举对象,所以Object.keys可以用来统计对象的属性。
var a = ['Hello', 'World'];
Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]
Object.keys(a).length // 2 统计对象的属性个数
3. 使用Object.prototype.toString构造更准确的变量类型判断函数
var type = function (o){
var s = Object.prototype.toString.call(o);
return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
type({}); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regex"
type(new Date()); // "date"
4. Object的静态方法
除了上面介绍的方法外,Object还有不少其他的静态方法
(1)对象属性模型的相关方法
- Object.getOwnPropertyDescriptor():获取某个属性的描述对象。
- Object.defineProperty():通过描述对象,定义某个属性。
- Object.defineProperties():通过描述对象,定义多个属性。
(2)控制对象状态的方法
- Object.preventExtensions():防止对象扩展。
- Object.isExtensible():判断对象是否可扩展。
- Object.seal():禁止对象配置。
- Object.isSealed():判断一个对象是否可配置。
- Object.freeze():冻结一个对象。
- Object.isFrozen():判断一个对象是否被冻结。
(3)原型链相关方法
- Object.create():该方法可以指定原型对象和属性,返回一个新的对象。
- Object.getPrototypeOf():获取对象的Prototype对象。
5. Object的实例方法
除了静态方法,还有不少方法定义在Object.prototype对象。它们称为实例方法,所有Object的实例对象都继承了这些方法。
Object实例对象的方法,主要有以下六个。
- Object.prototype.valueOf():返回当前对象对应的值。
- Object.prototype.toString():返回当前对象对应的字符串形式。
- Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。
- Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
- Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型。
- Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。
6. 如果一个对象静态方法和实例方法重名了会产生什么后果?
本题和访问对象的方法的顺序有关,首先检查对象自身有没有该方法,然后去对象的原型中去找,如果都没有找到就会顺着原型链一直往上找。
a = new Object()
b = new Object()
b.toString = function() { console.log('update') }
a.toString //"[object Object]"
b.toString //update
二、属性描述对象
JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。
举个例子:
var a = { name: 'zhangsan' }
//声明一个对象如a,但其实 name的属性对应的值并不是一个简单的字符串,而是一个对象
a = {
name: {
value: 'zhangsan' // 值
writable: false, // 是否可写
enumerable: true, // 是否可遍历
configurable: false, // 是否可配置
get: undefined, // 取值函数
set: undefined // 存值函数
}
}
// name属性后面的对象称之为描述对象,保存该属性的元信息。
1. 如何去查看一个对象的某个属性的描述对象
通过Object.getOwnPropertyDescriptor()方法可以获取属性描述对象。它的第一个参数是目标对象,第二个参数是一个字符串,对应目标对象的某个属性名。
var obj = { p: 'a' };
Object.getOwnPropertyDescriptor(obj, 'p')
// Object { value: "a",
// writable: true,
// enumerable: true,
// configurable: true
// }
2. 如何修改属性描述对象
Object.defineProperty()方法允许通过属性描述对象,定义或修改一个属性,然后返回修改后的对象,它的用法如下。
var obj = Object.defineProperty({}, 'p', {
value: 123,
writable: false,
enumerable: true,
configurable: false
});
obj.p // 123
obj.p = 246;
obj.p // 123
3. 如何拷贝一个对象
需要注意的是用 in 循环对象时可能会把不属于该对象本身的属性遍历了,所以需要注意使用 hasOwnProperty来验证该属性是否属于该对象,然后如果使用赋值语句对属性的值进行拷贝,那么也只能拷贝值而不能拷贝其描述对象,如何解决这个问题,请看示例代码:
var extend = function (to, from) {
for (var property in from) {
if (!from.hasOwnProperty(property)) continue;
Object.defineProperty(
to,
property,
Object.getOwnPropertyDescriptor(from, property)
);
}
return to;
}
extend({}, { get a(){ return 1 } })
网友评论