美文网首页
步遥——对象的扩展

步遥——对象的扩展

作者: 你还想好吗 | 来源:发表于2021-01-05 14:33 被阅读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或字符串,也不管是否可枚举。
    遍历顺序:

    • 首先遍历所有数值键,按照数值升序排列。
    • 其次遍历所有字符串键,按照加入时间升序排列。
    • 最后遍历所有 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 // 不报错,必须使用括号表明优先级
    

    相关文章

      网友评论

          本文标题:步遥——对象的扩展

          本文链接:https://www.haomeiwen.com/subject/wwzioktx.html