ES6:Object.assign方法详解

ES6:Object.assign方法详解

  • 1、前言
  • 2、语法
  • 3、基本用法
    • 3.1 目标对象和源对象无重名属性
    • 3.2 目标对象和源对象有重名属性
    • 3.3 有多个源对象
    • 3.4 其他情况
      • 3.4.1 只有一个参数时,Object.assign会直接返回该参数
      • 3.4.2 如果该参数不是对象,则会先转成对象,然后返回
      • 3.4.3 出现undefined和null情况
      • 3.4.4 其他类型的值
  • 4、高级用法
    • 4.1 为对象添加属性
    • 4.2 为对象添加方法
    • 4.3 克隆对象
    • 4.4 合并多个对象
    • 4.4 为属性指定默认值
  • 5、注意事项
  • 6、兼容性
  • 7、与$.extend()的比较

1、前言

首先了解下Object.assign()是什么。我们先看看ES6官方文档是怎么介绍的?

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

注意:Object.assign() 方法至少需要两个对象作为参数,第一个参数是目标对象,后面的参数都是源对象。

2、语法

语法:

Object.assign(target, ...sources)

参数:
target—>目标对象

source—>源对象

返回值:target,即目标对象

3、基本用法

3.1 目标对象和源对象无重名属性

var target = { name: '张三', age: 18 }
var source = { money: '10000' }
var result = Object.assign(target, source)
console.log(result)
console.log(target);

运行结果如下:
在这里插入图片描述
我们可以看到source上的state属性合并到了target对象上。如果只是想将两个或多个对象的属性合并到一起,不改变原有对象的属性,可以用一个空的对象作为target对象。像下面这样:

var target = { name: '张三', age: 18 }
var source = { money: '10000' }
var result = Object.assign({}, target, source)
console.log(result);

运行结果如下:
在这里插入图片描述

3.2 目标对象和源对象有重名属性

var target = { name: '张三', age: 18 }
var source = { money: '10000', age: 28 }
var result = Object.assign(target, source)
console.log(target)

运行结果如下:在这里插入图片描述
可以看到如果有同名属性的话,后面的属性值会覆盖前面的属性值。

3.3 有多个源对象

var target = { name: '张三', age: 18 }
var source1 = { money: '10000', age: 28 }
var source2 = { mood: 'happy', age: 25 }
var result = Object.assign(target, source1, source2)
console.log(target)

运行结果如下:
在这里插入图片描述
可以看到有多个源对象情况也是和一个源对象一样的。没有同名的属性会直接复制到目标对象上,同名的属性后面的属性值会覆盖前面的同名属性值。

3.4 其他情况

3.4.1 只有一个参数时,Object.assign会直接返回该参数

var obj = { a: 1 }
console.log(Object.assign(obj))
console.log(Object.assign(obj) === obj);

运行结果如下:
在这里插入图片描述

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

typeof Object.assign(2)  //  object 

3.4.3 出现undefined和null情况

由于undefined和null无法转成对象,所以如果将它们作为参数,就会报错。

Object.assign(undefined)
Object.assign(null)

运行结果如下:

在这里插入图片描述
注意:如果非对象参数出现在源对象的位置(即非首参数),那么处理规则将有所不同。首先,这些参数都会被转成对象,如果无法转成对象便会跳过。这意味着,如果undefined和null不在首参数便不会报错。

let obj = {
	a: 1
}
Object.assign(obj, undefined) === obj  // true
Object.assign(obj, null) === obj  // true

3.4.4 其他类型的值

其他类型的值(即数值、字符串、布尔值)不在首参数也不会出错。但是,除了字符串会以数组形式赋值到目标对象,其他值都不会产生效果。

var v1 = 'abc'
var v2 = true
var v3 = 10

var obj = Object.assign({}, v1, v2, v3)
console.log(obj);

运行结果如下:

在这里插入图片描述
上面的代码中,v1, v2, v3分别是字符串、布尔值和数值,结果只有字符串合入目标对象(以字符数组的形式),数值和布尔值都会被忽略。这是因为只有字符串的包装对象会产生枚举属性。

console.log(Object(true))
console.log(Object(10))
console.log(Object('abc'));

运行结果如下:
在这里插入图片描述
上面的代码中,布尔值、数值、字符串分别转成对应的包装对象,可以看到它们的原始值都在包装对象的内部属性[[PrimitiveValue]]上面,这个属性是不会被Object.assign() 复制的。只有字符串的包装会产生可枚举的实义属性,那些属性则会被拷贝。
Object.assign 复制的属性是有限制的,只复制源对象的自身属性(不复制继承属性),也不复制不可枚举的属性(enumerable: false)。

let obj = Object.assign({ b: 'c' },
   Object.defineProperty({}, 'invisible', {
        enumerable: false,
        value: 'hello world'
    })
)
console.log(obj);

运行结果如下:
在这里插入图片描述
上面的代码中,Object.assign要复制的对象只有一个不可枚举对属性invisible,这个属性并没有被复制进去。
属性名为Symbol值的属性也会被Object.assign复制。

let obj = Object.assign({ b: 'c' }, { [Symbol('c')]: 'd' })
console.log(obj);

运行结果如下:
在这里插入图片描述

4、高级用法

4.1 为对象添加属性

class Point {
    constructor(x, y) {
        Object.assign(this, { x, y })
        console.log(this)
    }
}
const p1 = new Point('12', '23')
console.log(p1);

运行结果如下:

在这里插入图片描述
上面的方法通过assign方法将x属性和y属性添加到了Point类的对象实例中。

4.2 为对象添加方法

Object.assign(SomeClass.prototype, {
    someMethod (argl, arg2) {
        ...
    },
    anotherMethod () {
        ...
    },
})
等同于下面的写法
SomeClass.prototype.someMethod = function (argl, arg2) {
	 ...
}
SomeClass.prototype.anotherMethod = function () {
	 ...
}

上面的代码使用了对象属性的简洁表示法,直接将两个函数放在大括号中,再使用assign方法添加到SomeClass.prototype中。

4.3 克隆对象

function clone (origin) {
	return Object.assign({}, origin)
}

上面的代码将原始对象复制到一个空对象中,就得到了原始对象的克隆。
不过,采用这种方法只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面这段代码。

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

4.4 合并多个对象

  • 将多个对象合并到某个对象
const merge = (target, ...sources) => Object.assign(target, ...sources);
  • 如果希望合并后返回一个新对象,可以改写上面的函数,对一个空对象合并。
const merge = (...sources) => Object.assign({}, ...sources);

4.4 为属性指定默认值

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

上面的代码中,DEFAULTS 对象是默认值,options对象是用户提供的参数。
Object.assign方法将DEFAULTS和options合并成一个新对象,如果两者有同名属性,则options的属性值会覆盖DEFAULTS 属性值。

注意:由于存在深复制的问题,DEFAULTS对象和options对象的所有属性
的值都只能是简单类型,而不能指向另一个对象,否则将导致DEFAULTS对象的该属性不起作用。

const DEFAULTS = {
   url: {
       host: 'example.corn',
       port: 7070
   }
}
processContent  ( {  url:  {port :  8000}  } )
//{
//  url:  {port:  8000)
//}

上面的代码原意是将url.port改成8000,而url.host保持不变。实际结果却是options.url覆盖了DEFAULTS.url,所以url.host就不复存在了。

5、注意事项

1、Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象,继承属性和不可枚举属性是不能拷贝的;

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

3、目标对象自身也会改变;

4、异常会打断后续拷贝任务;

5、Object.assign可以用来处理数组,但是会把数组视为对象来处理。

let obj = Object.assign([1, 2, 3], [4, 5])
console.log(obj);  // [4, 5, 3]

上面的代码中, Object.assign把数组视为属性名为0、1、2的对象,因此目标数组的0号属性覆盖了0号属性1。

6、兼容性

目前IE浏览器不兼容Object.assign(),如果需要兼容IE的话最好不要直接使用这个方法。

7、与$.extend()的比较

var target = { name: '张三', age: 18 }
var source1 = { state: 'single', age: 22 }
var source2 = { mood: 'happy', age: 25 }
var result = Object.assign(target, source1, source2)
console.log(target, 'assign')

var targetObj = { name: '张三', age: 18 }
var sourceObj1 = { state: 'single', age: 22 }
var sourceObj2 = { mood: 'happy', age: 25 }
var result = $.extend(targetObj, sourceObj1, sourceObj2)
console.log(targetObj, 'extend')

可以看到两者得到的结果是一样的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/44553.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

el-table 表头设置渐变色

<el-table :data"tableData" stripe><el-table-column prop"name" label"测试" align"left"></el-table-column><el-table-column prop"code" label"测试1" align"left"></…

科技云报道:边缘云赛道开启,谁能成为首个“出线”厂商?

科技云报道原创。 每一轮底层技术变革&#xff0c;都会带来全新的商业机遇。随着万物智联时代到来&#xff0c;大量数据产生的源头由传统的中心化向分散数据源变革&#xff0c;越来越多云边协同场景的出现&#xff0c;使得边缘云成为计算领域数据处理的新范式之一。 自2020年…

OR-Tools工具安装(Python-Vs code)-自用

安装&#xff08;已安装python以及Vs code&#xff09; pip安装 python -m pip install --user ortools安装完成示意如下&#xff1a; 验证安装 python -c "import ortools; print(ortools.__version__)"输出结果为版本号

网络:TCP/IP协议

1. OSI七层参考模型 应用层 表示层 会话层 传输层 网络层 数据链路层 物理层 2. TCP/IP模型 应用层 传输层 网络层 数据链路层 物理层 3. 各链路层对应的名称 应用层对应的是协议数据单元 传输层对应的是数据段 网络层对应的是数据包 链路层对应的是数据帧 物理层对应的是比特…

Mysql 简介

Mysql 简介 学习目的 MySQL作为目前最流行的关系型数据库管理系统之一&#xff0c;因其开源免费的特性&#xff0c;成为小型Web应用的重点关注对象。几乎所有的动态Web应用基本都在使用MySQL作为数据管理系统。学习MySQL的目的也是为了更好地理解数据库相关的SQL注入漏洞&…

uniapp实战

上面是tab栏&#xff0c;下面是swiper&#xff0c;&#xff0c;tab和swiper和 红色滑块 动态变化&#xff0c;&#xff0c; 遇到的问题&#xff1a; 往下滚动 tab栏 吸顶&#xff1a; position:sticky; z-index:99; top:0;swiper切换触发 change 事件&#xff0c; :current …

【Unity2D】相机移动以及设置相机边界

添加相机 添加相机时&#xff0c;首先需要在unity中添加 Cinemachine 包 第一次使用这个包时&#xff0c;需要在Package Manager中搜索并安装 安装Camera Mechine包后&#xff0c;添加2D Camera 设置跟随对象为Ruby &#xff08;从Hierarchy中将Ruby拖动到Follow中&#xff0…

UE5 关于MRQ渲染器参数

最佳参数&#xff1a; Spatial Sample Count&#xff1a;使用奇数样本时临时抗锯齿会收敛 Temporal Sample Count&#xff1a;超过2之后&#xff0c;采样过大会造成TAA效果不佳 TSR&#xff1a;UE5最好的抗锯齿方案

AcWing241. 楼兰图腾(树状数组)

输入样例&#xff1a; 5 1 5 3 2 4输出样例&#xff1a; 3 4解析&#xff1a; 以某个点 i 为最低点的 V 的数量&#xff0c;为 i 左侧和右侧比 a[ i ] 大的数量 a&#xff0c;b 的乘积。 但是&#xff0c;直接求这两个数的复杂度为O(n)&#xff0c;则整个复杂度为O( n^2 )&am…

js基础-练习三

九九乘法表&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthsc, initial-scale1.0"><title>九九乘法表</title><style&g…

可解释的 AI:在transformer中可视化注意力

Visualizing Attention in Transformers | Generative AI (medium.com) 一、说明 在本文中&#xff0c;我们将探讨可视化变压器架构核心区别特征的最流行的工具之一&#xff1a;注意力机制。继续阅读以了解有关BertViz的更多信息&#xff0c;以及如何将此注意力可视化工具整合到…

论文笔记--Distilling the Knowledge in a Neural Network

论文笔记--Distilling the Knowledge in a Neural Network 1. 文章简介2. 文章概括3 文章重点技术3.1 Soft Target3.2 蒸馏Distillation 4. 文章亮点5. 原文传送门 1. 文章简介 标题&#xff1a;Distilling the Knowledge in a Neural Network作者&#xff1a;Hinton, Geoffre…

iOS 单元测试之常用框架 OCMock 详解

目录 前言&#xff1a; 一、单元测试 1.1 单元测试的必要性 1.2 单元测试的目的 - 约束条件是否通过形式参数来传送。 1.3 单元测试依赖的两个主要框架 二、OCMock 的集成与使用 2.1 OCMock 的集成方式 2.2 OCMock 的使用方法 2.3 mock 使用限制 前言&#xff1a; OC…

IDEA+SpringBoot + Mybatis + Shiro+Bootstrap+Mysql资产设备管理系统

IDEASpringBoot Mybatis ShiroBootstrapMysql资产设备管理系统 一、系统介绍1.环境配置 二、系统展示1. 管理员登录2.用户新增3.用户设置4.岗位管理5. 审批节点6. 人员查询7. 组织设置8. 人员调整9.角色设置10.角色模块映射11.模块设置12.应用模块13.光纤交换机14.服务器15.网…

从实践彻底掌握MySQL的主从复制

目录 一、本次所用结构如图---一主多从级联&#xff1a; 二、IP。 三、配置M1&#xff1a; 四、从库M1S1&#xff1a; 五、从库M2配置&#xff1a; 六、 从库M2S1&#xff1a; 一、本次所用结构如图--- 一主多从级联&#xff1a; 二、IP。这里M1S1和M1S2一样的&#xff0…

hack the box—Lame

扫描 还是老方法nmapfscan得到开放的端口和服务 nmap -sV -sC -sT -v -T4 10.10.10.3 看到开了445&#xff0c;先来波ms17-010&#xff0c;发现失败。 这里还开个21&#xff0c;并且可以知道版本号&#xff0c;直接搜索ftp漏洞 msf正好有对应的模块 设置好参数后进行攻击&…

Hadoop 集群如何升级?

前言 本文隶属于专栏《大数据技术体系》&#xff0c;该专栏为笔者原创&#xff0c;引用请注明来源&#xff0c;不足和错误之处请在评论区帮忙指出&#xff0c;谢谢&#xff01; 本专栏目录结构和参考文献请见大数据技术体系 正文 升级 Hadoop 集群需要细致的规划&#xff0c;特…

【设计模式】单例设计模式详解(包含并发、JVM)

文章目录 1、背景2、单例模式3、代码实现1、第一种实现&#xff08;饿汉式&#xff09;为什么属性都是static的&#xff1f;2、第二种实现&#xff08;懒汉式&#xff0c;线程不安全&#xff09;3、第三种实现&#xff08;懒汉式&#xff0c;线程安全&#xff09;4、第四种实现…

树莓派刷机和登入

1.打开映像工具 2.选择映像文件写入 3.拔出卡插入树莓派上电 4.树莓派登入 1.HDMI视频线&#xff0c;连接到显示屏幕 2.串口登录 修改系统配置&#xff0c;启用串口登录树莓派 &#xff08;1) 打开SD卡根目录的"config.txt文件"&#xff0c;停止蓝牙&#xff0c;…

使用lua脚本操作redis

redis中实现事务有两种方法&#xff1a; 1.WATCH监视键的变动&#xff0c;然后MULTI开始事务&#xff0c;EXEC提交事务 WATCH key [key…]&#xff1a;监视一个或多个键&#xff0c;如果在事务执行之前被修改&#xff0c;则事务被打断。 MULTI&#xff1a;标记一个事务的开始。…