• ES6之主要知识点(七)对象


    1.属性的简洁表示法

    ES6 允许直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

    function f(x, y) {
      return {x, y};
    }
    
    // 等同于
    
    function f(x, y) {
      return {x: x, y: y};
    }
    
    f(1, 2) // Object {x: 1, y: 2}
    var o = {
      method() {
        return "Hello!";
      }
    };
    
    // 等同于
    
    var o = {
      method: function() {
        return "Hello!";
      }
    };
    module.exports = { getItem, setItem, clear };
    // 等同于
    module.exports = {
      getItem: getItem,
      setItem: setItem,
      clear: clear
    };

    2.Object.is() 

    ES6 提出“Same-value equality”(同值相等)算法。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,

    与严格比较运算符(===)的行为基本一致。

    Object.is('foo', 'foo')
    // true
    Object.is({}, {})
    // false
    +0 === -0 //true
    NaN === NaN // false
    
    Object.is(+0, -0) // false
    Object.is(NaN, NaN) // true

    3.Object.assign() 

    Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

    Object.assign(target, source1, source2);

    Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。

    注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。

    如果该参数不是对象,则会先转成对象,然后返回。

    typeof Object.assign(2) // "object"
    let obj = {a: 1};
    Object.assign(obj, undefined) === obj // true
    Object.assign(obj, null) === obj // true

    Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false

    注意点

    Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用

    常见用途 

    (1)为对象添加属性

    class Point {
      constructor(x, y) {
        Object.assign(this, {x, y});
      }
    }

    (2)克隆对象

    function clone(origin) {
      let originProto = Object.getPrototypeOf(origin);
      return Object.assign(Object.create(originProto), origin);
    }

    (3)为属性指定默认值

    const DEFAULTS = {
      logLevel: 0,
      outputFormat: 'html'
    };
    
    function processContent(options) {
      options = Object.assign({}, DEFAULTS, options);
      console.log(options);
      // ...
    }

    注意,由于存在浅拷贝的问题,DEFAULTS对象和options对象的所有属性的值,最好都是简单类型,不要指向另一个对象。 

    4.属性的可枚举性和遍历

    可枚举性

    对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。

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

    描述对象的enumerable属性,称为”可枚举性“,如果该属性为false,就表示某些操作会忽略当前属性。

    目前,有四个操作会忽略enumerablefalse的属性。

    • for...in循环:只遍历对象自身的和继承的可枚举的属性。
    • Object.keys():返回对象自身的所有可枚举的属性的键名。
    • JSON.stringify():只串行化对象自身的可枚举的属性。
    • Object.assign(): 忽略enumerablefalse的属性,只拷贝对象自身的可枚举的属性。

    属性的遍历

    ES6 一共有5种方法可以遍历对象的属性。

    (1)for...in

    for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。

    var a ={'b':232,'cc':'dd'}
    for(let temp in a){
        console.log(temp)
    }
    //2 b
    //2 cc

    (2)Object.keys(obj)

    Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)。

    (3)Object.getOwnPropertyNames(obj)

    Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)。

    (4)Object.getOwnPropertySymbols(obj)

    Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性。

    (5)Reflect.ownKeys(obj)

    Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管属性名是 Symbol 或字符串,也不管是否可枚举。

    5.Object.getOwnPropertyDescriptors()

    前面说过,Object.getOwnPropertyDescriptor方法会返回某个对象属性的描述对象(descriptor)。

    ES2017 引入了Object.getOwnPropertyDescriptors方法,返回指定对象所有自身属性(非继承属性)的描述对象。

    const obj = {
      foo: 123,
      get bar() { return 'abc' }
    };
    
    Object.getOwnPropertyDescriptors(obj)
    // { foo:
    //    { value: 123,
    //      writable: true,
    //      enumerable: true,
    //      configurable: true },
    //   bar:
    //    { get: [Function: bar],
    //      set: undefined,
    //      enumerable: true,
    //      configurable: true } }

    该方法的引入目的,主要是为了解决Object.assign()无法正确拷贝get属性和set属性的问题。

    Object.getOwnPropertyDescriptors方法的一个用处,是配合Object.create方法,将对象属性克隆到一个新对象。这属于浅拷贝

    const clone = Object.create(Object.getPrototypeOf(obj),
      Object.getOwnPropertyDescriptors(obj));
    

     

    6.__proto__属性,Object.setPrototypeOf(),Object.getPrototypeOf()

    __proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。目前,所有浏览器(包括 IE11)都部署了这个属性。

    Object.setPrototypeOf方法的作用与__proto__相同,用来设置一个对象的prototype对象,返回参数对象本身。它是 ES6 正式推荐的设置原型对象的方法。

    let proto = {};
    let obj = { x: 10 };
    Object.setPrototypeOf(obj, proto);
    
    proto.y = 20;
    proto.z = 40;
    
    obj.x // 10
    obj.y // 20
    obj.z // 40

    Object.getPrototypeOf() 

    function Rectangle() {
      // ...
    }
    
    var rec = new Rectangle();
    
    Object.getPrototypeOf(rec) === Rectangle.prototype
    // true
    
    Object.setPrototypeOf(rec, Object.prototype);
    Object.getPrototypeOf(rec) === Rectangle.prototype
    // false

    7.Object.keys(),Object.values(),Object.entries()

    let {keys, values, entries} = Object;
    let obj = { a: 1, b: 2, c: 3 };
    
    for (let key of keys(obj)) {
      console.log(key); // 'a', 'b', 'c'
    }
    
    for (let value of values(obj)) {
      console.log(value); // 1, 2, 3
    }
    
    for (let [key, value] of entries(obj)) {
      console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
    }

    Object.values只返回对象自身的可遍历属性

    Object.entries的基本用途是遍历对象的属性。

    Object.entries方法的另一个用处是,将对象转为真正的Map结构。

    var obj = { foo: 'bar', baz: 42 };
    var map = new Map(Object.entries(obj));
    map // Map { foo: "bar", baz: 42 }

    8.Null 传导运算符 

    编程实务中,如果读取对象内部的某个属性,往往需要判断一下该对象是否存在。

    比如,要读取message.body.user.firstName,安全的写法是写成下面这样。

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

    这样的层层判断非常麻烦,因此现在有一个提案,引入了“Null 传导运算符”(null propagation operator)?.,简化上面的写法。

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

    “Null 传导运算符”有四种用法。

    • obj?.prop // 读取对象属性
    • obj?.[expr] // 同上
    • func?.(...args) // 函数或对象方法的调用
    • new C?.(...args) // 构造函数的调用 

    9.Object.defineProperty()

    语法:

    Object.defineProperty(obj, prop, descriptor)

    参数说明:

    obj:必需。目标对象 
    prop:必需。需定义或修改的属性的名字
    descriptor:必需。目标属性所拥有的特性
    Object.defineProperty(obj,"newKey",{
        configurable:true | false,
        enumerable:true | false,
        value:任意类型的值,
        writable:true | false,
        get:function (){
            //当获取值的时候触发的函数
            return initValue;    
        },
        set:function (value){
            //当设置值的时候触发的函数,设置的新值通过参数value拿到
            initValue = value;
        }
    });
  • 相关阅读:
    http和socket之长连接和短连接区别【转】
    Linux下内存泄漏工具【转】
    arm交叉编译器gnueabi、none-eabi、arm-eabi、gnueabihf等的区别【转】
    C语言字节对齐 __align(),__attribute((aligned (n))),#pragma pack(n)【转】
    简单解读linux的/proc下的statm、maps、memmap 内存信息文件分析【转】
    linux调试工具glibc的演示分析-core dump double free【转】
    Linux信号(signal)机制【转】
    细说JavaScript对象(4): for in 循环
    细说JavaScript对象(3):hasOwnProperty
    细说JavaScript对象(2):原型对象
  • 原文地址:https://www.cnblogs.com/myzy/p/7563006.html
Copyright © 2020-2023  润新知