JavaScript Object 对象方法
Object.defineProperty
Object.defineProperty(obj, prop, descriptor) 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。方法接收三个参数:分别为需定义属性的目标对象、属性名和熟悉描述符。
descriptor 属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个拥有可写或不可写值的属性。存取描述符是由一对 getter-setter 函数功能来描述的属性。描述符必须是两种形式之一;不能同时是两者。
数据描述符和存取描述符两种形式下均可选键值:
- configurable true 表示该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
- enumerable true 表示该属性能够出现在对象的枚举属性(for in、Objecet.keyes)中。默认为 false。
数据描述符可选键值:
- value 该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
- writable true 表示该属性能被赋值运算符改变。默认为 false。
存取描述符可选键值:
- get 该方法返回值被用作属性值。默认为 undefined。
- set 接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。
// 数据描述符使用
function withValue(value) { // 循环使用同一对象
var d = withValue.d || (
withValue.d = {
enumerable: false,
writable: false,
configurable: false,
value: null
}
);
d.value = value;
return d;
}
var obj = {};
Object.defineProperty(obj, "key", withValue("static"));
使用存取描述符,可实现数据绑定,观察者模式。
var bValue;
Object.defineProperty(o, "b", {
get : function(){
return bValue;
},
set : function(newValue){
bValue = newValue;
},
enumerable : true,
configurable : true
});
o.b = 38; // 对象o拥有了属性b,值为38
Object.getOwnPropertyDescriptor
返回对象的属性描述符,只能取得对象自身的属性描述符而不能获取原型对象的属性描述符。
var object1 = {
property1: 42
}
var descriptor = Object.getOwnPropertyDescriptor(object1, 'property1');
console.log(descriptor.configurable); // true
Object.create
使用指定的原型对象或属性对象,创建一个新的对象
var o;
// 创建一个原型为null的空对象
o = Object.create(null);
o = {};
// 以字面量方式创建的空对象就相当于:
o = Object.create(Object.prototype);
o = Object.create(Object.prototype, {
// foo会成为所创建对象的数据属性
foo: {
writable:true,
configurable:true,
value: "hello"
},
// bar会成为所创建对象的访问器属性
bar: {
configurable: false,
get: function() { return 10 },
set: function(value) {
console.log("Setting `o.bar` to", value);
}
}
});
function Constructor(){}
o = new Constructor();
// 上面的一句就相当于:
o = Object.create(Constructor.prototype);
// 当然,如果在Constructor函数中有一些初始化代码,Object.create不能执行那些代码
// 创建一个以另一个空对象为原型,且拥有一个属性p的对象
o = Object.create({}, { p: { value: 42 } })
// 省略了的属性特性默认为false,所以属性p是不可写,不可枚举,不可配置的:
o.p = 24
o.p
//42
o.q = 12
for (var prop in o) {
console.log(prop)
}
//"q"
delete o.p
//false
//创建一个可写的,可枚举的,可配置的属性p
o2 = Object.create({}, {
p: {
value: 42,
writable: true,
enumerable: true,
configurable: true
}
});
Object.assign
用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。返回目标对象。如果属性存在,后面的参数对象会覆盖掉前面的。拷贝深度仅为一层,假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。
- 继承属性和不可枚举属性不能拷贝
var obj = Object.create({foo: 1}, { // foo 是个继承属性。
bar: {
value: 2 // bar 是个不可枚举属性。
},
baz: {
value: 3,
enumerable: true // baz 是个自身可枚举属性。
}
});
var copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }
- 拷贝访问器
var obj = {
foo: 1,
get bar() {
return 2;
}
};
var copy = Object.assign({}, obj);
// { foo: 1, bar: 2 }
// copy.bar的值来自obj.bar的getter函数的返回值
console.log(copy);
// 下面这个函数会拷贝所有自有属性的属性描述符
function completeAssign(target, ...sources) {
sources.forEach(source => {
let descriptors = Object.keys(source).reduce((descriptors, key) => {
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
return descriptors;
}, {});
// Object.assign 默认也会拷贝可枚举的Symbols
Object.getOwnPropertySymbols(source).forEach(sym => {
let descriptor = Object.getOwnPropertyDescriptor(source, sym);
if (descriptor.enumerable) {
descriptors[sym] = descriptor;
}
});
Object.defineProperties(target, descriptors);
});
return target;
}
var copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }
Object.keys
返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 for-in 循环还会枚举其原型链上的属性)。
与 Object.hasOwnProperty 和 in 操作符检测检测的属性不同的是,后两者检测对象是否存在某个属性,不论属性是否可被枚举。
Object.hasOwnProperty 只会检测对象自身是否存在属性,而不会检测原型链上的对象。
in 操作符可检测一切对象及其原型链上对象存在的属性。
var pro = {'a': 1};
var obj = Object.create(pro);
Object.defineProperties(obj, {
'b': {value: 2},
'c': {value: 3, enumerable: true},
'd': {value: 4, configurable: true}
});
Object.keys(obj);
// ['c']
for(var prop in obj) {
console.log(prop);
}
// output
// 'c'
// 'a'
'a' in obj
// true
'b' in obj
// true
obj.hasOwnProperty('a')
// false
obj.hasOwnProperty('b')
// true
Object.getPrototypeOf
返回指定对象的原型
var proto = {};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true