对象拓展

属性的简洁表示法

使用简写属性的办法:const baz = {foo};等价于const baz = {foo: foo};
ES6 表达对象的新形式,使用表达式的情况:

let propkey = "dd";
let obj = {
  [propkey]: true,
  ["a" + "bc"]: 123,
};
//甚至可以定义方法名:
let obj = {
  ["h" + "ello"]() {
    return "a";
  },
};
//不能同时使用属性名表达式和简洁记法
const keya = { a: 1 };
let obj = {
  [keya]: "a",
};
//会自动将对象转为字符串[object Object]

//使用取值函数和存值函数,一般来说使用方法的name属性可以返回函数名
//1.对于set和get函数来说,直接通过访问set.name和get.name获取
//bind方法创造的函数,doSomething.bind().name // "bound doSomething"
//对于Function构造函数创造的函数,返回anonymous
const obj={
    get foo(){},
    set foo(x){}
}
const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
descriptor.get.name // "get foo"
descriptor.set.name // "set foo"
//使用Symbol值来作为属性
const key1 = Symbol('description');
const key2 = Symbol();
let obj = {
  [key1]() {},
  [key2]() {},
};
obj[key1].name // "[description]"

对象的每个属性有一个描述对象获取描述值:

Object.getOwnPropertyDescriptor(obj, 'foo')
//  {
//    value: 123,
//    writable: true,
//    enumerable: true,
//    configurable: true
//  }

enumerable属性称为"可枚举性",有4个操作只考虑可枚举的:

  • for...in...,包括可继承属性(于for of的区别在一个是索引,一个是值)
  • Object.keys()返回可枚举的属性的键名
  • 串行化对象自身的可枚举属性JSON.stringify()
  • Object.assign()只拷贝可枚举属性

super关键字

super指向原型对象,super.foo指向原型对象,绑定的this还是当前对象obj

const proto = {
  x: 'hello',
  foo() {
    console.log(this.x);
  },
};
const obj = {
  x: 'world',
  foo() {
    super.foo();
  }
}
Object.setPrototypeOf(obj, proto);
obj.foo() // "world"

对象的解构赋值,且为浅拷贝,但不复制继承自原型对象的属性,即不带上对应的原型:

let {x,y,...z}={x:1,y:2,a:3,b:4};
z // { a: 3, b: 4 }
//例子:自有对象自身的属性可以使用这种解构
const o = Object.create({ x: 1, y: 2 });
o.z = 3;
let { x, ...newObj } = o;
let { y, z } = newObj;
x // 1
y // undefined
z // 3

解构赋值可以用来扩展函数的参数,而由于数组是特殊对象所以也可以使用到数组上进行。

完整拷贝一个对象及对应的原型有三种写法:

// 写法一
const clone1 = {
  __proto__: Object.getPrototypeOf(obj),
  ...obj
};
// 写法二
const clone2 = Object.assign(
  Object.create(Object.getPrototypeOf(obj)),
  obj
);
// 写法三
const clone3 = Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
)

同名覆盖:
let aWithOverrides = { ...a, ...{ x: 1, y: 2 } };

如果使用了取值函数get,在扩展运算符的参数对象中会执行对应的get函数.

链式判断

在需要层层判断的场景下,我们会这样写:

const firstName = (message
  && message.body
  && message.body.user
  && message.body.user.firstName) || 'default';
//或者使用三元运算符

有三种用法:

  • obj?.prop
  • obj?.[expr]
  • func?.(...args)
(a?.b).c//只对内部括号的有影响,对外部没影响
a?.b = c//注意不能为?.3,即右边不可以为数字

新的默认值符号:??当左边只为null或undefined时,才生效,而||会在左边为空串或者false或者0时也会生效。

posted @ 2022-10-17 15:23  梦呓qwq  阅读(16)  评论(0编辑  收藏  举报