属性的拓展

属性的简介表示法

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'}复制代码