zoukankan      html  css  js  c++  java
  • Object.assign()解释整理

    链接:https://blog.csdn.net/wang252949/article/details/79106160

    语法

    Object.assign(target, ...sources)

    参数

    target
    目标对象。
    sources
    源对象。

    返回值

    目标对象。

    描述

    如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖。后来的源的属性将类似地覆盖早先的属性。

    Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()Object.defineProperty() 。

    String类型和 Symbol 类型的属性都会被拷贝。

    在出现错误的情况下,例如,如果属性不可写,会引发TypeError,如果在引发错误之前添加了任何属性,则可以更改target对象。

    注意,Object.assign 会跳过那些值为 null 或 undefined 的源对象。

    示例

    复制一个对象

    1.  
      var obj = { a: 1 };
    2.  
      var copy = Object.assign({}, obj);
    3.  
      console.log(copy); // { a: 1 }

    深拷贝问题

    针对深拷贝,需要使用其他方法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。

    1.  
      functiontest(){
    2.  
      'use strict';
    3.  
       
    4.  
      let obj1 = { a: 0 , b: { c: 0}};
    5.  
      let obj2 = Object.assign({}, obj1);
    6.  
      console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
    7.  
       
    8.  
      obj1.a = 1;
    9.  
      console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
    10.  
      console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}}
    11.  
       
    12.  
      obj2.a = 2;
    13.  
      console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}}
    14.  
      console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
    15.  
       
    16.  
      obj2.b.c = 3;
    17.  
      console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}}
    18.  
      console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}}
    19.  
       
    20.  
      // Deep Clone
    21.  
      obj1 = { a: 0 , b: { c: 0}};
    22.  
      let obj3 = JSON.parse(JSON.stringify(obj1));
    23.  
      obj1.a = 4;
    24.  
      obj1.b.c = 4;
    25.  
      console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
    26.  
      }
    27.  
       
    28.  
      test();

    合并对象

    1.  
      var o1 = { a: 1 };
    2.  
      var o2 = { b: 2 };
    3.  
      var o3 = { c: 3 };
    4.  
       
    5.  
      var obj = Object.assign(o1, o2, o3);
    6.  
      console.log(obj); // { a: 1, b: 2, c: 3 }
    7.  
      console.log(o1); // { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。

    合并具有相同属性的对象

    1.  
      var o1 = { a: 1, b: 1, c: 1 };
    2.  
      var o2 = { b: 2, c: 2 };
    3.  
      var o3 = { c: 3 };
    4.  
       
    5.  
      var obj = Object.assign({}, o1, o2, o3);
    6.  
      console.log(obj); // { a: 1, b: 2, c: 3 }

    属性被后续参数中具有相同属性的其他对象覆盖。

    拷贝 symbol 类型的属性

    1.  
      var o1 = { a: 1 };
    2.  
      var o2 = { [Symbol('foo')]: 2 };
    3.  
       
    4.  
      var obj = Object.assign({}, o1, o2);
    5.  
      console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
    6.  
      Object.getOwnPropertySymbols(obj); // [Symbol(foo)]

    继承属性和不可枚举属性是不能拷贝的

    1.  
      var obj = Object.create({foo: 1}, { // foo 是个继承属性。
    2.  
      bar: {
    3.  
      value: 2 // bar 是个不可枚举属性。
    4.  
      },
    5.  
      baz: {
    6.  
      value: 3,
    7.  
      enumerable: true // baz 是个自身可枚举属性。
    8.  
      }
    9.  
      });
    10.  
       
    11.  
      var copy = Object.assign({}, obj);
    12.  
      console.log(copy); // { baz: 3 }

    原始类型会被包装为对象

    1.  
      var v1 = "abc";
    2.  
      var v2 = true;
    3.  
      var v3 = 10;
    4.  
      var v4 = Symbol("foo")
    5.  
       
    6.  
      var obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
    7.  
      // 原始类型会被包装,null 和 undefined 会被忽略。
    8.  
      // 注意,只有字符串的包装对象才可能有自身可枚举属性。
    9.  
      console.log(obj); // { "0": "a", "1": "b", "2": "c" }

    异常会打断后续拷贝任务

    1.  
      var target = Object.defineProperty({}, "foo", {
    2.  
      value: 1,
    3.  
      writable: false
    4.  
      }); // target 的 foo 属性是个只读属性。
    5.  
       
    6.  
      Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
    7.  
      // TypeError: "foo" is read-only
    8.  
      // 注意这个异常是在拷贝第二个源对象的第二个属性时发生的。
    9.  
       
    10.  
      console.log(target.bar); // 2,说明第一个源对象拷贝成功了。
    11.  
      console.log(target.foo2); // 3,说明第二个源对象的第一个属性也拷贝成功了。
    12.  
      console.log(target.foo); // 1,只读属性不能被覆盖,所以第二个源对象的第二个属性拷贝失败了。
    13.  
      console.log(target.foo3); // undefined,异常之后 assign 方法就退出了,第三个属性是不会被拷贝到的。
    14.  
      console.log(target.baz); // undefined,第三个源对象更是不会被拷贝到的。

    拷贝访问器

    1.  
      var obj = {
    2.  
      foo: 1,
    3.  
      get bar() {
    4.  
      return 2;
    5.  
      }
    6.  
      };
    7.  
       
    8.  
      var copy = Object.assign({}, obj);
    9.  
      // { foo: 1, bar: 2 }
    10.  
      // copy.bar的值来自obj.bar的getter函数的返回值
    11.  
      console.log(copy);
    12.  
       
    13.  
      // 下面这个函数会拷贝所有自有属性的属性描述符
    14.  
      functioncompleteAssign(target,...sources){
    15.  
      sources.forEach(source => {
    16.  
      let descriptors = Object.keys(source).reduce((descriptors, key)=> {
    17.  
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
    18.  
      return descriptors;
    19.  
      }, {});
    20.  
       
    21.  
      // Object.assign 默认也会拷贝可枚举的Symbols
    22.  
      Object.getOwnPropertySymbols(source).forEach(sym => {
    23.  
      let descriptor = Object.getOwnPropertyDescriptor(source, sym);
    24.  
      if (descriptor.enumerable) {
    25.  
      descriptors[sym] = descriptor;
    26.  
      }
    27.  
      });
    28.  
      Object.defineProperties(target, descriptors);
    29.  
      });
    30.  
      return target;
    31.  
      }
    32.  
       
    33.  
      var copy = completeAssign({}, obj);
    34.  
      console.log(copy);
    35.  
      // { foo:1, get bar() { return 2 } }

    Polyfill

    polyfill不支持 symbol 属性,因为ES5 中根本没有 symbol :

    1.  
      if (typeof Object.assign != 'function') {
    2.  
      // Must be writable: true, enumerable: false, configurable: true
    3.  
      Object.defineProperty(Object, "assign", {
    4.  
      value: functionassign(target, varArgs){ // .length of function is 2
    5.  
      'use strict';
    6.  
      if (target == null) { // TypeError if undefined or null
    7.  
      throw new TypeError('Cannot convert undefined or null to object');
    8.  
      }
    9.  
       
    10.  
      var to = Object(target);
    11.  
       
    12.  
      for (var index = 1; index < arguments.length; index++) {
    13.  
      var nextSource = arguments[index];
    14.  
       
    15.  
      if (nextSource != null) { // Skip over if undefined or null
    16.  
      for (var nextKey in nextSource) {
    17.  
      // Avoid bugs when hasOwnProperty is shadowed
    18.  
      if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
    19.  
      to[nextKey] = nextSource[nextKey];
    20.  
      }
    21.  
      }
    22.  
      }
    23.  
      }
    24.  
      return to;
    25.  
      },
    26.  
      writable: true,
    27.  
      configurable: true
    28.  
      });
    29.  
      }
    个人分类: 前端开发JavaScript
  • 相关阅读:
    VPS CenteOS Linux 上传 下载文件(Apache配置、SSH)
    tar命令加密压缩
    操作系统命令技巧备忘录
    网络流量分析-PCAP切割、筛选、合并
    【Shell】30分钟关闭Tcpdump,开启Tcpdump、检测目录大小终止任务
    大数据做安全的网站
    WinRAR代码执行漏洞CVE-2018-20250
    Linux嗅探ettercap
    WindowsPE权威指南-PE文件头中的重定位表
    推荐书籍-恶意软件分析诀窍与工具箱
  • 原文地址:https://www.cnblogs.com/wulihong/p/9295967.html
Copyright © 2011-2022 走看看