Javascript 中对象属性与方法汇总
1. Object 构造函数的方法
需要通过构造函数调用,如
Object.keys()
1. Object.assign()
用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象
const obj = {
name: 'obj name'
};
const copy = Object.assign(obj, {
a: 'aaa'
});
console.log(copy === obj);
// 更多的时候用来合并对象
const a = {
name: 'name a'
};
Object.defineProperty(a, 'b', {
value: 'prop b',
enumerable: false // 不可枚举
});
const b = {
name: 'name b',
type: 'object'
};
const copy = Object.assign({}, a, b);
console.log(copy); // { name: 'name b', type: 'object' } 相同的属性会被覆盖
console.log(a.b); // prop b
console.log(copy.b); // undefined 继承属性和不可枚举属性的属性不能拷贝
2. Object.create()
使用指定的原型对象及一些属性去创建一个新的对象,第二个参数是一个新添加属性的描述符集合,与
Object.defineProperties()
第二个参数类似
const proto = {
name: 'proto name'
};
const a = Object.create(proto, {
// getName 会成为 创建对象的属性
getName: {
// 值为一个属性描述符
value: function() {
return this.name;
}
}
});
console.log(a.getName());
// 创建一个原型为 null 的空对象
const b = Object.create(null);
console.log(b);
3. Object.defineProperty()
在一个对象上定义一个新的属性,或者修改一个对象的现有属性,并返回对象,允许精确添加或修改对象的属性
const obj = {
a: 'number is 1.32'
};
// 给 obj 对象上定义 ‘b’ 属性
Object.defineProperty(obj, 'b', {
value: 'default value', // 该属性对应的值,可以是任意类型
writable: true, // 是否可写,true 表示可以被运算符改变
enumerable: true, // 是否可枚举,可枚举的属性才可以被 in 运算符检查和被 Object.keys() 返回
configurable: false // 目前定义的描述符是否是可以修改的, 设置为 true 不但可以被修改,此属性也可以被删除
});
4. Object.defineProperties()
在一个对象上定义新的属性或修改现有属性,并返回该对象,与 defineProperty 区别是可以定义多个属性
const obj = {
name: 'obj name'
};
Object.defineProperties(obj, {
getName: {
value: function() {
return this.name;
}
},
changeName: {
value: function(name) {
this.name = name;
}
}
});
console.log(obj.getName()); // obj name
obj.changeName('xxx');
console.log(obj.getName()); // xxx
5. Object.freeze()
Object.isFrozen()
Object.freeze()
用于冻结一个对象,冻结后,不能向这个对象添加新的属性,不能修改其已有属性的值,不能删除已有属性,包括其已有属性的描述符都不能修改,该方法会返回被冻结对象
Object.isFrozen()
判断是否已冻结
const child = {
id: 'child id'
};
const obj = {
name: 'obj name',
child: child
};
console.log(obj); // { name: 'obj name', child: { id: 'child id' } }
// 冻结
const freeze = Object.freeze(obj);
console.log(Object.isFrozen(obj)); // true 判断是否冻结
console.log(freeze === obj); // true
// 尝试改变属性
obj.name = 'new name';
console.log(obj.name); // obj name 没有改变
// 尝试添加
obj.newProp = 'new prop';
console.log(obj.newProp); // undefined 添加失败
// 更改属性中的对象内容,但指针地址不变
child.id = 'new id';
console.log(obj.child); // { id: 'new id' } 可以改变
6. Object.preventExtensions()
Object.isExtensible()
Object.preventExtensions()
使得一个对象变得不可扩展,不能添加新属性
Object.isExtensible()
判断是否是不可扩展的对象
const a = {
name: 'a'
};
// 使不可扩展
Object.preventExtensions(a);
console.log(Object.isExtensible()); // false 不可扩展
// 尝试添加新属性
a.type = 'type';
console.log(a.type); // undefined 不可以添加新属性
// 尝试更改原属性
a.name = 'new name';
console.log(a.name); // new name 可以更改原属性
7. Object.seal()
Object.isSealed()
Object.seal()
让一个对象密封,并返回被密封后的对象。密封对象将会阻止向对象添加新的属性,并且会将所有已有属性的可配置性(configurable)置为不可配置(false),即不可修改属性的描述或删除属性。但是可写性描述(writable)为可写(true)的属性的值仍然可以被修改。
Object.isSealed()
判断是否是密封的
// MDN 上的例子
const obj = {
prop: function() {},
foo: 'bar'
};
// 可以添加新的属性,已有属性的值可以修改,可以删除
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;
const o = Object.seal(obj);
console.log(o === obj); // true
console.log(Object.isSealed(obj) === true); // true
// 仍然可以修改密封对象上的属性的值.
obj.foo = 'quux';
// 但你不能把一个数据属性重定义成访问器属性.
Object.defineProperty(obj, 'foo', {
get: function() {
return 'g';
}
}); // 抛出TypeError异常
// 现在,任何属性值以外的修改操作都会失败.
obj.quaxxor = 'the friendly duck'; // 静默失败,新属性没有成功添加
delete obj.foo; // 静默失败,属性没有删除成功
8. Object.is()
判断两个值是否相等,与传统的判断方法
==
===
不太一样
const a = {
name: 'a'
};
const b = {
name: 'a'
};
Object.is(a, b); // false
Object.is([], []); // false
Object.is(null, null); // true
Object.is(0, -0); // false
Object.is(NaN, NaN); // true
9. Object.getOwnPropertyDescriptor()
返回指定对象上一个自有属性的描述符
const proto = {
protoName: 'proto name'
};
const obj = Object.create(proto, {
name: {
value: 'obj name'
}
});
console.log(Object.getOwnPropertyDescriptor(obj, 'name'));
/*
{
value: 'obj name',
writable: false,
enumerable: false,
configurable: false
}
*/
console.log(obj.protoName); // proto name 可以获取到
console.log(Object.getOwnPropertyDescriptor(obj, 'protoName')); // undefined 不能得到原型链上的属性
10. Object.getPrototypeOf()
返回指定对象的原型
const proto = {
protoName: 'proto name'
};
const obj = Object.create(proto, {
name: {
value: 'obj name'
}
});
console.log(Object.getPrototypeOf(obj) === proto); // true
11. Object.keys()
返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for…in 循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)。
const proto = {
protoName: 'proto name'
};
const obj = Object.create(proto, {
name: {
value: 'obj name',
enumerable: true // 设置为可枚举,否则遍历不到
},
age: {
value: 'obj age',
enumerable: false // 设置为不可枚举,这样不会被遍历到
}
});
let arr = [];
for (const key in obj) {
arr.push(key);
}
console.log(arr); // [ 'name', 'protoName' ] for-in 循环会遍历原型链上的可枚举属性
console.log(Object.keys(obj)); // [ 'name' ] Object.keys() 只返回自身的可枚举属性
12. Object.values()
返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用 for…in 循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
const proto = {
protoName: 'proto name'
};
const obj = Object.create(proto, {
name: {
value: 'obj name',
enumerable: true // 设置为可枚举,否则遍历不到
},
age: {
value: 'obj age',
enumerable: false // 设置为不可枚举,这样不会被遍历到
}
});
console.log(Object.values(obj));
/*
[ 'obj name' ]
Object.values() 只返回自身的可枚举属性的值
不可枚举的与原型链上的属性都没有返回
*/
13. Object.entries()
返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for…in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)。
const proto = {
protoName: 'proto name'
};
const obj = Object.create(proto, {
name: {
value: 'obj name',
enumerable: true // 设置为可枚举,否则遍历不到
},
age: {
value: 'obj age',
enumerable: false // 设置为不可枚举,这样不会被遍历到
}
});
console.log(Object.entries(obj));
/*
[ [ 'name', 'obj name' ] ]
Object.entries() 只返回自身的可枚举属性的键值对
不可枚举的与原型链上的属性都没有返回
*/
14. Object.getOwnPropertyNames()
返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组
const proto = {
protoName: 'proto name'
};
const obj = Object.create(proto, {
name: {
value: 'obj name',
enumerable: true // 设置为可枚举,否则遍历不到
},
age: {
value: 'obj age',
enumerable: false // 设置为不可枚举,这样不会被遍历到
}
});
const key = Symbol('key');
obj[key] = 'symbol value';
console.log(Object.getOwnPropertyNames(obj));
/*
[ 'name', 'age' ]
Object.getOwnPropertyNames() 只返回自身的属性名集合
包括不可枚举的属性,但是不包括 Symbol 类型的属性名
*/
14. Object.getOwnPropertySymbols()
返回一个给定对象自身的所有 Symbol 属性的数组
const proto = {
protoName: 'proto name'
};
const obj = Object.create(proto, {
name: {
value: 'obj name',
enumerable: true
}
});
const key = Symbol('key');
obj[key] = 'symbol value';
const symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols); // [ Symbol(key) ]
symbols.forEach(symbol => console.log(symbol.constructor)); // [Function: Symbol]
2. Object.prototype
Object 原型对象(或者对象实例)上的属性与方法
几乎所有的 JavaScript 对象都是
Object
的实例,一个典型的对象会继承Object.prototype
的属性和方法
1. .constructor
返回创建实例对象的构造函数的引用
const o = {};
o.constructor === Object; // true
const a = [];
a.constructor === Array; // true
const num = 20;
num.constructor === Number; // true
2. .hasOwnProperty()
返回一个布尔值,指示对象自身是否具有指定的属性
const obj = {
getVal() {
return this.val;
}
};
obj.__proto__.val = 'prototype val';
Object.defineProperty(obj, 'b', {
value: 'bbb',
enumerable: false // 一个不可枚举属性
});
console.log(obj);
console.log(obj.getVal()); // 'prototype val'
console.log(obj.hasOwnProperty('val')); // false
console.log(obj.hasOwnProperty('b')); // true
3. .isPrototypeOf()
用于测试一个对象是否存在于另一个对象的原型链上
const protoObj = {
proto: 'proto obj'
};
// Object.create(proto); 表示 以 proto 为原型创建对象
const obj = Object.create(protoObj);
console.log(obj.proto); // proto obj
console.log(protoObj.isPrototypeOf(obj)); // true
4. .propertyIsEnumerable()
判断指定属性是否是可枚举的
const obj = {};
Object.defineProperty(obj, 'a', {
enumerable: false, // 不可枚举
value: 'aaa'
});
console.log(obj.a);
console.log(Object.prototype.propertyIsEnumerable.call(obj, 'a')); // false
5. .toString()
返回一个对象的字符串表示
const a = {
name: 'a name'
};
function Test() {}
const b = new Test();
console.log(a.toString()); // [object Object]
console.log(b.toString()); // [object Object]
/*
Function Array String 等类型的 toString() 方法都有被覆盖
如果想使用 toString()检测对象类型 可以用如下的方法
*/
const arr = ['xxx', 'yyy'];
const fun = function() {};
console.log(arr.toString()); // xxx,yyy
console.log(fun.toString()); // function () {}
console.log(Object.prototype.toString.call(arr)); // [object Array]
console.log(Object.prototype.toString.call(fun)); // [object Function]
6. .toLocaleString()
同样是返回一个对象的字符串表示,但是可以用于派生对象为了特定语言环境的目的(locale-specific purposes)而重载使用。
Array\Number\Date 等内置对象都有对这个方法的覆盖,在一般 Object 中其返回的结果与
toString()
一致
const arr = [{}, 1231, function() {}, new Date()];
console.log(arr.toString()); // [object Object],1231,function () {},Sun Feb 11 2018 11:17:09 GMT+0800 (CST)
console.log(arr.toLocaleString()); // [object Object],1,231,function () {},2018-2-11 11:17:09
7. .valueOf()
返回指定对象的原始值
const obj = {
name: 'obj name'
};
console.log(obj.valueOf()); // { name: 'obj name' }