属性的拓展
属性的简介表示法
ES6允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let a = 1 let age={ a } console.log(age) //{a:1}复制代码
除了属性可以简写之外,方法也可以简写
let f = { foo(){} } //相当于 let f = { foo:function () {} }复制代码
在函数返回值的时候,可以这样写
function add(x, y) { let x = x + 1 let y = y + 1 return { x, y } }复制代码
CommonJS模板输出一组变量,可以这样写
function getItem(key) { return obj[key] } function setItem(key, value) { obj[key] = value } module.exports = { getItem, setItem }复制代码
属性的可枚举性与遍历
对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。
let foo = { age:20 } Object.getOwnPropertyDescriptor(foo,'age') //{ configurable: true, enumerable: true, value: 20 writable: true }复制代码
如果enumerable属性为false,则不可以用以下方法来进行遍历
- for...in循环:只遍历对象自身的和继承的可枚举的属性。
- Object.keys():返回对象自身的所有可枚举的属性的键名。
- JSON.stringify():只串行化对象自身的可枚举的属性。
- Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
遍历对象的方法
let symbol = Symbol() let foo = { age: 20, name: 'David', [symbol]: 'symbol' }复制代码
- for...in
for...in循环遍历对象自身的和继承的可枚举属性(不含Symbol属性)。
for (let i in foo) { console.log(i) // age name }复制代码
- Object.keys(obj)
Object.keys()返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)的键名。
Object.keys(foo).forEach(item => {
console.log(item) //age name
})复制代码
- Object.values(obj)
Objec.values()返回一个数组,包括对象自身(不含继承的)的所有可枚举属性的键值(不含Symbol属性)
Object.values(foo).forEach(item => {
console.log(item) //20 David
})复制代码
- Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames()返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性)的键名。
Object.getOwnPropertyNames(foo) //['age','name']复制代码
- Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols()返回一个数组,包含对象自身的所有 Symbol 属性的键名。
Object.getOwnPropertySymbols(foo) //[Symbol()]复制代码
- Reflect.ownKeys(obj)
Reflect.ownKeys()返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
Reflect.ownKeys(foo) //[ 'age', 'name', Symbol() ]复制代码
对象的新增方法
Object.is()
ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.is('foo', 'foo'), //true Object.is(+0, -0), //false Object.is(NaN, NaN), //true Object.is([], []) //false复制代码
不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
Object.assign()
Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
let target = { a: 1 } let source1 = { b: 2 } let source2 = { c: 3 } target //{ a: 1, b: 2, c: 3 }复制代码
但是Object.assign()方法实行的是浅拷贝,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
Object.getOwnPropertyDescriptors()
ES5的Object.getOwnPropertyDescriptor()方法会返回某个对象属性的描述对象(descriptor)。ES2017引入了Object.getOwnPropertyDescriptors()方法,返回指定对象所有自身属性(非继承属性)的描述对象。
let obj = { age: 20, name: 'David' } Object.getOwnPropertyDescriptor(obj, 'age') //{ value: 20, writable: true, enumerable: true, configurable: true } Object.getOwnPropertyDescriptors(obj) { age:{ value: 20, writable: true, enumerable: true, configurable: true }, name:{ value: 'David', writable: true, enumerable: true, configurable: true } } 复制代码
__proto__属性、Object.setPrototypeOf()、Object.getPrototypeOf()
JavaScript语言的对象继承是通过原型链实现的。ES6 提供了更多原型对象的操作方法。
__proto__属性
__proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。
const obj = { method: function() { ... } }; obj.__proto__ = someOtherObj;复制代码
Object.setPrototypeOf()
Object.setPrototypeOf()方法的作用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象本身
Object.setPrototypeOf(obj,someOtherObj)复制代码
Object.getPrototypeOf()
该方法与Object.setPrototypeOf()方法配套,用于读取一个对象的原型对象。
Object.getPrototypeOf(obj)
Object.entries()
Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组。
Object.entries(foo) //[ [ 'age', 20 ], [ 'name', 'David' ] ]复制代码
Object.fromEntries()
Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。
Object.fromEntries([ ['age', 20], ['name', 'David'] ]) //{age:20,name:'David'}复制代码