JavaScript ES6 - 对象扩展

本章节的主要内容是: ES6 对象扩展

: 对象扩展
    1. 属性的简洁表示方法
    2. 属性表达式
    3. 扩展运算符
    4. Object 新增方法

如图所示:
JavaScript ES6 - 对象扩展_第1张图片

1. ES6 属性的简洁表示方法: {}

/**
1.1 普通属性
 */
// ES5 对象写法
{
  // 示例一
  let str1 = '字符'
  let num1 = 11111
  let objES5 = {
    str1: str1,
    num1: num1
  }
  console.log('ES5 对象写法: ', objES5); // ES5 对象写法:  {str1: '字符', num1: 11111}
}
// ES6 写法
{
  // 示例一
  // 对比 ES5 对象写法中的 '示例一', 它们的结果并没有什么不同, 只是写法上更加简洁 。
  let str1 = '字符'
  let num1 = 11111
  let objES6 = {
    str1,
    num1
  }
  console.log('ES6 对象写法: ', objES6); // ES6 对象写法:  {str1: '字符', num1: 11111}
}


/**
1.2 对象中的方法
    1. ES6 中的写法比 ES5 中的写法简洁的多: 我们可以将 " : 与 function " 关键字省去 。
 */
// ES5 写法
{
  let es5_method = {
    hello: function() {
      console.log('ES5 中方法的写法 -- 使用方法对比是否不同 (ES5)');
    }
  }
  es5_method.hello() // ES5 中方法的写法 -- 使用方法对比是否不同 (ES5)
}
// ES6 写法
{
  let es6_method = {
    hello() {
      console.log('ES6 中方法的写法 -- 使用方法对比是否不同 (ES6) ');
    }
  }
  es6_method.hello() // ES6 中方法的写法 -- 使用方法对比是否不同 (ES6)
}


/**
1.3 函数返回值
 */
{
  function fun1() {
    let x = 1
    let y = 2
    // ES6 写法
    return {x, y}

    // // ES5 实现方法
    // return {
    //   x: x,
    //   y: y
    // }
  }
  console.log(fun1()); // {x: 1, y: 2}
}


/**
1.4 CommonJS 模块输出变量
 */
// 假设下面的代码是一个 .JS 文件中的内容, 使用 CommonJS 模块化方法输出内容
{
  var ms = {a: 1}
  function fn1() {
    return 1 + 2
  }
  function fn2() {
    return 2+3
  }
  function fn3() {
    ms = {}
  }
  // moudle.exports = {
  //   ms,
  //   fn1,
  //   fn2,
  //   fn3
  // }
}

2. 属性名表达式: []

/**
2. 属性名表达式: []
   1. 在 ES5 中, 对象的 key 值是固定的; 在 ES6 中 key 值是可以用表达式也可以使用变量来作为 key 使用的 。
   2. 注意细节知识点:
      1. '属性名表达式' 与 '简介表示法' 不能同时使用, 否则会报错 。
 */
// ES5 写法
{
  let a = 'abc'
  let es5_obj = {
    a: 'ddddd'
  }
  console.log(es5_obj); // {a: 'ddddd'}
}

// ES6 写法
{
  let a = 'abc'
  let es6_obj = {
    // 字面量定义对象的属性名
    [a]: 'ddddd',

    // 表达式作为对象的属性名
    ['k' + 'ey' + 'Val']: 'kkkkk',

    // 表达式用于定于方法名
    ['f' + 'un' + '1']() {
      return '表达式用于定于方法名'
    }
  }
  console.log(es6_obj); // {abc: 'ddddd', keyVal: 'kkkkk', fun1: ƒ}
}

3. ES6 对象扩展运算符: …

/**
3. 扩展运算符 ...
   1. 结构赋值:
      1. 对象的解构赋值用于从一个对象取值, 相当于将所有可遍历的、但尚未被读取的属性分配到指定的对象上 。
      2. 注意:
         1. 对象的解构赋值要求等号右边是一个对象; 如果等号右边是 undefined 或 null 会报错, 因为它们不能转换为对象 。
         2. 解构赋值的复制是浅复制 。
   1. 注意:
      1. 为了正常运行当前语法, 我们需要安装: cnpm install babel-preset-stage-2 --save; 在 .babelrc 文件中 presets 选项中, 添加 "stage-2" 。
      2. 通常安装到 stage-2 就够用了, 如果还不行, 再安装 stage-1 或者 stage-0 <越小越新> 。
   1.
 */

{
  // 解构赋值:
  let {a, b, ...c} = {a: '1', b: '2', c: '3', d: '4'}
  console.log('对象的扩展运算符: ', c); // 对象的扩展运算符:  {c: '3', d: '4'}


  // undefined 或 null 会报错
  // let {a1, b1, ...c1} = undefined // 报错
  // let {a2, b2, ...c2} = null // 报错


  // 解构赋值的复制是浅复制

}

4. ES6 Object 新增方法

4.1 ES6 新增方法: Object.is()

/**
4.1 Object.is()
    1. 判断两个值是否相等
 */
{
  console.log('判断两个字符串是否相等: ', 'ES6: ', Object.is('abc', 'abc'), 'ES5: ', 'abc' === 'abc'); // 判断两个字符串是否相等:  ES:  true ES5:  true

  /**
   * 1. 数组是引用类型, 虽然都是空数组, 在值上都是空, 但是这两个数组引用的是两个不同的地址, 所以在严格意义上来讲它们是不相等的 。
   * 2. Object.is() 的功能与 ===(严格相等运算符) 的功能没有区别 。
   */
  console.log('判断两个数组是否相等<引用类型>', 'ES6: ', Object.is([], []), 'ES5: ', [] === []); // 判断两个数组是否相等<引用类型> ES6:  false ES5:  false
}

4.2 ES6 新增方法: Object.assign()

/**
4.2 Object.assign()
    1. 拷贝功能
    2. 细节知识点:
       1. Object.assign 实现的是浅拷贝  。
          1. 浅拷贝只拷贝引用地址, 而不是将值真正的拷贝过去 。
          2. 这个方法拷贝的只是自身的属性, 如果这个对象还有继承属性, 它是不会拷贝继承属性的 。
          3. 同时也不能拷贝不可枚举的属性 。
 */
{
  let obj1 = {a: 'a'}
  let obj2 = {b: 'b'}
  let objAss = Object.assign(obj1, obj2)
  console.log('拷贝功能: ', objAss, obj1, obj2); // 拷贝功能:  {a: 'a', b: 'b'} {a: 'a', b: 'b'} {b: 'b'}
  // 修改
  obj2.b = '111111111'
  console.log('修改: 单层深拷贝 ----- : ', objAss, obj1, obj2) // 修改 ----- :  {a: 'a', b: 'b'} {a: 'a', b: 'b'} {b: '111111111'}

  // 源对象属性的值为对象 
  let a1 = {a: '111'}
  let a2 = {b: '222', c: {d: '3333'}}
  let asA = Object.assign({}, a1, a2)
  console.log(asA, a1, a2); // {a: '111', b: '222', c: {d: '3333'}} {a: '111'} {b: '222', c: {d: '3333'}}
  a2.c.d = '修改属性值为对象的结果---3333'
  console.log(asA, a1, a2); // {a: '111', b: '222', c: {d: '修改属性值为对象的结果---3333'}} {a: '111'} {b: '222', c: {d: '修改属性值为对象的结果---3333'}}



  // 注意: 如果目标对象与源对象有同名属性, 或者多个源对象有同名属性, 则后面的属性会覆盖前面的属性
  let o1 = {a:1, b:2}
  let o2 = {b: 3, c: 4}
  let o3 = {c: 5}
  Object.assign(o1, o2, o3)
  console.log('属性覆盖 -- o1: ', o1); // 属性覆盖 -- o1:  {a: 1, b: 3, c: 5}


  // 如果只有一个参数, Object.assign 会直接返回该参数
  let b1 = {a: 2}
  console.log('只有一个参数 -- b1: ', Object.assign(b1) === b1); // 只有一个参数 -- b1:  true
}



// 为对象添加属性:
{
  class Point {
    constructor(x, y) {
      // 通过 Object.assign 方法将 x 、 y 属性添加到 Point 类的对象实例中 。
      Object.assign(this, {x, y})
    }
  }
  // let point = new Point
  // console.log(point.x);
}



// 为对象添加方法:
{
  class SomeClass {}
  Object.assign(SomeClass.prototype, {
    // 直接将两个函数放在大括号中, 使用 Object.assign 方法添加到 SomeClass.prototype 中
    someMethod(arg1, arg2) {

    },
    anotherMethod() {

    }

  })
}

6. ES6 Object.getOwnPropertyDescriptor()

/**
5. Object.getOwnPropertyDescriptor()
   1. 可以获取属性的描述对象 。

   1. 属性的可枚举型:
 */
{
  let obj1 = {foo: 123}
  console.log(Object.getOwnPropertyDescriptor(obj1, 'foo'));
  // 打印结果:
  // {
  //   value: 123,
  //   writable: true, // 对象属性是否可修改; flase 为不可修改, 默认值为 true 。
  //   enumerable: true, // 可枚举型; 如果为 false, 某些操作可以忽略当前属性 。
  //   configurable: true // 能否使用 delete / update, 能否需改属性特性 、 或能否修改访问器属性; false 为不可重新定义, 默认值为 true 。
  // }
  /**
   * 1. Object.assign 会忽略 enumerable 为 false 的属性, 只赋值对象的可枚举属性 。
   * 2. 注意:
   *    1. ES6 规定, class 的原型的方法都是不可枚举的 。
   */
}

7. ES6 属性的遍历

/**
6. 属性的遍历
   1. for...in    : 循环遍历对象自身和继承的可枚举属性(不含 Symbol 属性) 。
   2. Object.keys(obj)    : 返回数组; 对象自身<不包含继承>和可枚举属性(不含 Symbol 属性) 。
   3. Object.getOwnPropertyNames(obj)    : 返回数组; 包含自身的所有属性 <不含 Symbol 属性, 但是包含不可枚举的属性> 。
   4. Object.getOwnPropertySymbols(obj)  : 返回一个数组; 包含自身所有的 Symbol 属性 。
   5. Reflect.ownKeys(obj)   : 返回一个数组; 包含对象自身的所有属性, 不管属性名是 Symbol 还是字符串, 也不管是否可枚举 。

   细节知识点:
   1. Object.keys() 与 Reflect.ownKeys() 的区别:
      1. Object.keys() 返回属性 key, 但不包括不可枚举的属性 。
      2. Reflect.ownKeys() 返回所有属性 key 。
 */
{
  let obj = {
    a: 1,
    b: {b1: 2},
    c: [3, 4],
    d: {
      d1: 5,
      d2: {d3: 6},
      d4: {d5: [7,8]}
    },
    [Symbol()]: 123
  }
  // for...in
  for (const key in obj) {
    if (Object.hasOwnProperty.call(obj, key)) {
      console.log('属性的遍历--for...in: ', key);
      // // 打印结果:
      // 属性的遍历--for...in:  a
      // 属性的遍历--for...in:  b
      // 属性的遍历--for...in:  c
      // 属性的遍历--for...in:  d
    }
  }

  // Object.keys(obj)
  console.log('属性的遍历--Object.keys: ', Object.keys(obj)); // 属性的遍历--Object.keys:  ['a', 'b', 'c', 'd']

  // Object.getOwnPropertyNames
  console.log('属性的遍历--Object.getOwnPropertyNames: ', Object.getOwnPropertyNames(obj));
  // 打印结果:
  // 属性的遍历--Object.getOwnPropertyNames:  ['a', 'b', 'c', 'd']

  // Object.getOwnPropertySymbols
  console.log('属性的遍历--Object.getOwnPropertySymbols: ', Object.getOwnPropertySymbols(obj));
  // 打印结果:
  // 属性的遍历--Object.getOwnPropertySymbols:  [Symbol()]

  // Object.ownKeys
  console.log('属性的遍历--Reflect.ownKeys: ', Reflect.ownKeys(obj));
  // 打印结果:
  // 属性的遍历--Reflect.ownKeys:  ['a', 'b', 'c', 'd', Symbol()]
}

8. keys() / values() / entries()

/**
7. keys() / values() / entries() : 用于遍历对象 <与数组的 keys() / values() / entries() 用法相同, 可参考数组中的用法>
   1. keys(): 对 键名 的遍历 。
   2. values(): 对 键值 的遍历 。
   3. entries(): 对 键值对 的遍历 。
 */

以上代码执行结果, 如图所示:
JavaScript ES6 - 对象扩展_第2张图片
之前有整理过部分知识点, 现在将整理的相关内容, 验证之后慢慢分享给大家; 这个专题是 “前端ES6基础” 的相关专栏; 不积跬步,无以至千里, 戒焦戒躁 。

如果对大家有所帮助,可以点个关注、点个赞; 文章会持续打磨 。
有什么想要了解的前端知识, 可以在评论区留言, 会及时分享所相关内容 。

你可能感兴趣的:(JavaScript,ES6语法解析,javascript,前端,开发语言,es6,面向对象编程)