链接: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

Object.assign()解释整理的更多相关文章

  1. ngx-bootstrap使用03 Alerts组件、利用Object.assign复制对象

    1 Alerts 该组件用于给用户操作提供反馈信息或者提供一些警告信息 2 用法 2.1 下载ngx-bootstrap依赖 参考博文:点击前往 2.2 在模块级别导入AlertModule模块 技巧 ...

  2. javascript学习总结之Object.assign()方法详解

    最近再写ES6的文章时候发现自己对Object.assign()方法不太了解,之前也没有接触过所以就就查阅了相关的资料,为了自己以后肯能会用到以及对知识进行巩固,所以在这里记录下自己学习的点点滴滴,毕 ...

  3. js中的Object.assign接受两个函数为参数的时候会发生什么?

    缘由 今天看到一段代码 return Object.assign(func1, func2); 心生疑惑,为什么 Object.assign 的参数可以是函数? 于是有了下面这一堆东西,其实都是老生常 ...

  4. 一个 Object.assign 的误解

    mozilla中对 Object.assign 的解释如下地址: mozilla 其中有说到 注意, Object.assign 会跳过那些值为 null 或 undefined 的源对象. 一直以为 ...

  5. Object.assign方法复制或合并对象

    Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象 var obj = { a: 1 }; var copy = Object.assign({ ...

  6. Object.assign()方法

    对象的扩展 1.ES6中,对象的属性和方法可简写:对象的属性值可不写,前提是属性名已经声明: var name = "zhangsan"; "; var obj = { ...

  7. 微信不支持Object.assign

    微信不支持Object.assign,让我Vue怎么用QAQ... 解决方法: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Refe ...

  8. object.assign()方法的使用

    地址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

  9. [Javascript] Object.assign()

    Best Pratices for Object.assign: http://www.cnblogs.com/Answer1215/p/5096746.html Object.assign() ca ...

随机推荐

  1. es6学习日记3

    函数的扩展 ES6 之前,不能直接为函数的参数指定默认值,只能采用变通的方法. function log(x, y) { y = y || 'World'; console.log(x, y); } ...

  2. 几个特殊的IP地址

    1)私有地址     IP地址在全世界范围内唯一,看到这句话你可能有这样的疑问,像192.168.0.1这样的地址在许多地方都能看到,并不唯一,这是为何?Internet管理委员会规定如下地址段为私有 ...

  3. Linux跨服务器发送文件

    在要发送的文件所在的目录下,输入下列命令 第一种: scp -r test.jar root@127.0.0.1:$(pwd)/test.jar 其中root为服务器账户名,127.0.0.1为要发送 ...

  4. CF1109D Sasha and Interesting Fact from Graph Theory

    CF1109D Sasha and Interesting Fact from Graph Theory 这个 \(D\) 题比赛切掉的人基本上是 \(C\) 题的 \(5,6\) 倍...果然数学计 ...

  5. some working learning总结学习(二)

    2. 读取excel上的测试用例和结果,成json格式,最终存到access数据库 结果如下: { : { 'Req_ID': 'Fqqqqq/qqqqq', 'Case_ID': 'ATC_LvPw ...

  6. html对a标签的运用以及属性,img图像标签的属性及应用

    今天学习的难点自我感觉在于a标签超链接的应用.不是很熟练,晚上回家准备敲敲代码,让a的超链接标签使用的更加熟练,对于上午的img 属性值已经明白 . 还是日常记一下每日的重点   a标签去下划线:a{ ...

  7. python魔法方法

    1.__call__ 实现__call__后,该类的对象可以被调用 举例如: class test_call_: def __init__(self, n): self.n = n def __cal ...

  8. 【BZOJ2555】SubString

    算是学会sam了吧…… 原题: 懒得写背景了,给你一个字符串init,要求你支持两个操作        (1):在当前字符串的后面插入一个字符串        (2):询问字符串s在当前字符串中出现了 ...

  9. PythonStudy——魔法函数 Magic Methods

    魔法函数 python中以双下划线开始和结束的函数(不可自己定义)为魔法函数 调用类实例化的对象的方法时自动调用魔法函数(感觉不需要显示调用的函数都叫) 在自己定义的类中,可以实现之前的内置函数,比如 ...

  10. Python的paramiko,实现ssh

    最简单的使用paramiko登录远程机器执行一些命令,学习实验楼的paramiko记录下来,第一次使用ConfigParser这个库,对于封装这些还是不太熟悉,只能慢慢来,嘿嘿嘿 这是python脚本 ...