步遥——对象的扩展

2021-01-05  本文已影响0人  你还想好吗

对象的扩展

对象本身的数据结构的改变:
1:属性的简洁表示:允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简单

const foo = 'df'
const baz = {foo} //等同于{foo:foo}
baz // {foo: "df"}

2:方法也可以简写

const o = {
method(){return 'hello!'}   //等同于 method:function(){return 'hello!'}
}
o.method() // 'hello!'

3:属性名表达式
es5只有标识符定义属性,es6允许表达式做对象的属性名,即把表达式放在方括号内。

let propKey = 'foo'
let obj= {
[propKey]:true
}
obj  // {foo: true}

4:方法名也可以是表达式

let obj = {
  ['h' + 'eo']() {
    return 'hi';
  }};
obj.heo() // hi

如果属性名是对象,会被转为字符串[object Object]
对象的属性可以是字符串和symbol类型

5:对象方法的name属性
因为对象的方法名可以是字符串,symbol,方法也可以是get,set方法,所以name的值也有不同

普通的字符串,则返回对应的字符串
get,set方法的name需要在属性描述符的set,get属性上获取

const obj = {
  get foo() {},
  set foo(x) {}
};

obj.foo.name
// TypeError: Cannot read property 'name' of undefined
const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');

descriptor.get.name // "get foo"
descriptor.set.name // "set foo"

symbol值的会返回symbol的描述

6:属性的可枚举和遍历
每个属性都可以通过Object.getOwnPropertyDescriptor获取到任意一个属性的可配置的属性:比如值,是否可枚举,是否可配置,是否可修改等

class的原型的方法都是不可枚举的,在循环时尽量不要使用for...in ,而使用Object.keys();

7:遍历属性的方法:

7.1:for...in // 循环遍历对象自身的和继承的可枚举属性,不含symbol
7.2:Object.keys() // 返回一个数组,包括对象自身的不含继承的所有可枚举属性的键名,不含symbol
7.3:Object.getOwnPropertyNames //返回一个数组,包含对象自身的所有属性不包含symbol,但是包含不可枚举属性的键名
7.4:Object.getOwnPropertySymbols // 返回一个数组,包含对象自身的所有symbol属性的键名
7.5:Reflect.ownKeys //返回一个数组,包含对象自身的不含继承的所有键名,不管键名是symbol或字符串,也不管是否可枚举。
遍历顺序:

8:super关键字
指向当前对象的原型对象,并且只能用在对象的方法中。目前只有对象方法的简写法可以让js引擎确认,定义的是对象的方法:

let obj ={
foo:2
}

let obj1 ={
method(){  //对象方法的简写中可以使用super
return super.foo
}
}
obj1.method()//2

setPrototypeOf & getPrototypeOf 
Object.setPrototypeOf(obj,prototype) //将prototype设置为obj的原型
Object.getPrototypeOf(obj) // 返回obj的原型对象

8:对象的解构赋值:
对象的解构赋值用于从一个对象取值,相当于将目标对象自身的所有可遍历的(enumerable)、但尚未被读取的属性,分配到指定的对象上面。所有的键和它们的值,都会拷贝到新对象上面

解构赋值要求等号右边是一个对象,undefined和null会报错
解构赋值必须是最后一个参数
解构赋值是浅拷贝
解构赋值不能复制继承自原型对象的属性

用处:扩展某个函数的参数,引入其他操作

9:扩展运算符
用于取出参数对象的所有可遍历属性,拷贝到当前对象之中
扩展运算符后面不是对象,则会自动转为对象

扩展运算符后是数字,布尔,undefined,null,都会返回空对象

对象的扩展运算符等同于使用Object.assign()方法

let aClone = {...obj} //
let aClone1 = Object.assign({},obj)//同上只拷贝对象实例属性,像完整克隆一个对象,还拷贝对象原型的属性,可以采用下面的写法

const aClone2 = Object.assign(Object.create(Object.getPrototyOf(obj)),obj) // 将原型和对象合并

如果用户自定义的属性,放在扩展运算符后面,则扩展运算符内部的同名属性会被覆盖掉。 这用来修改现有对象部分的属性就很方便了,新的值会覆盖前面的属性
与数组的扩展运算符一样,对象的扩展运算符后面可以跟表达式

用处:合并对象

10:链判断运算符

const  firstName = message.body.user.firstName;

es5:
const firstName = (message
  && message.body
  && message.body.user
  && message.body.user.firstName) || 'default';

es6:
const firstName = message?.body?.user?.firstName || 'default';

判断方法是否存在并执行

iterator.return?.()
obj1.method?.() // 2
obj1.aaa?.() // undefined

链判断语法:
* obj?.prop // 对象属性
* obj?.[expr] // 同上
* func?.(...args) // 函数或对象方法的调用
判断数组是否有值

let hex = "#C0FFEE".match(/#([A-Z]+)/i)?.[1];

链判断特点:
短路机制
delete运算符,失败则不删除
如果属性链有圆括号,链判断运算符对圆括号外部没有影响,只对圆括号内部有影响
链判断运算符的左侧不能是 super
链判断不能用来赋值
右侧不得为十进制数值

12:Null判断运算符 ??

左侧只有等于null或undefined的时候,才会返回右侧的值,如果为‘’ 或false的时候,还返回‘’或false

用处:
就是跟链判断运算符?.配合使用,为null或undefined的值设置默认值。

如果多个逻辑运算符一起使用,必须用括号表明优先级,否则会报错。

lhs && middle ?? rhs //报错
(lhs && middle) ?? rhs // 不报错,必须使用括号表明优先级
上一篇下一篇

猜你喜欢

热点阅读