(译文)JavaScript基础——JavaScript中的深拷贝
在JavaScript中如何拷贝一个对象?
通过引用调用
function mutate(obj) {
obj.a = true;
}
const obj = {a: false};
mutate(obj)
console.log(obj.a); // prints true
mutate可以对obj进行改动,然后外面的obj的值也变化了。
浅拷贝:Object.assign()
一种拷贝方式是这种方法: Object.assign(target, sources...).
const obj = /* ... */;
const copy = Object.assign({}, obj);
但是这种拷贝只是浅拷贝:
function mutateDeepObject(obj) {
obj.a.thing = true;
}
const obj = {a: {thing: false}};
const copy = Object.assign({}, obj);
mutateDeepObject(copy)
console.log(obj.a.thing); // prints true
JSON.parse
通过转换为字符串,然后再转回来:
const obj = /* ... */;
const copy = JSON.parse(JSON.stringify(obj));
这样不好的地方是你会处理一个大的字符串,并且无法处理
循环对象:
const x = {};
const y = {x};
x.y = y; // Cycle: x.y.x.y.x.y.x.y.x...
const copy = JSON.parse(JSON.stringify(x)); // throws!
而且像Maps, Sets, RegExps, Dates, ArrayBuffers和其他内置对象序列化的时候可能都有问题。
结构化克隆
它是一种算法,将一个值转换为另外一个值。而且能处理对象循环依赖和大部分的内置对象。比如调用postMessage发消息给window或者WebWorker的时候就用到。
比如像这样:obj是被深拷贝过的
function structuralClone(obj) {
return new Promise(resolve => {
const {port1, port2} = new MessageChannel();
port2.onmessage = ev => resolve(ev.data);
port1.postMessage(obj);
});
}
const obj = /* ... */;
const clone = await structuralClone(obj);
历史API
如果你用过history.pushState()去构建一个单页应用(SPA),你应该知道你可以根据当前URL保存一个state object。这个state object是结构化拷贝的,并且是同步的。
function structuralClone(obj) {
const oldState = history.state;
history.replaceState(obj, document.title);
const copy = history.state;
history.replaceState(oldState, document.title);
return copy;
}
const obj = /* ... */;
const clone = structuralClone(obj);
不好的地方是Safari限制replaceState的调用次数。
通知API
function structuralClone(obj) {
return new Notification('', {data: obj, silent: true}).data;
}
const obj = /* ... */;
const clone = structuralClone(obj);
性能如何
结论是:
1 如果你不处理对象依赖和内置对象,可以直接用 JSON.parse(JSON.stringify())
2 如果你要可靠的跨浏览器支持:用MessageChannel
原文:
https://dassur.ma/things/deep-copy/#call-by-reference
作者知乎/公众号:前端疯
(译文)JavaScript基础——JavaScript中的深拷贝的更多相关文章
- JavaScript基础——JavaScript入门(笔记)
JavaScript入门(笔记) JavaScript是一种轻量级.解释型的Web开发语言,该语言系统不是很庞杂,简单易学.由于所有现代浏览器都已嵌入JavaScript引擎,JavaScript源代 ...
- Javascript基础 - js中曾经忽略的知识点
深入那些曾经忽略的Javascript知识 1. parseInt(string, [radix]),parseFloat(string) 一般我们省略第二个参数,parseInt(‘100’) == ...
- JavaScript基础内容中的函数详解
函数 函数:即方法 函数就是一段预先设置的功能代码块,可以反复调用,根据输入参数的不同,返回不同的值. 为什么使用函数: 1.方便调用 2.代码重用,利于维护 3.便于修改,便于重构 4.简化逻辑,利 ...
- JavaScript基础函数体中的唯一var模式(002)
全局变量是不好的.所以在声名变量的时候,应该采用函数体中的唯一var模式(Single var Pattern).这个模式有不少好处: 提供了一个唯一的地方来查看函数体中声名的变量 在使用一个变量之前 ...
- JavaScript基础Javascript中的循环(003)
1.普通循环JavaScript中一般的循环写法是这样的: // sub-optimal loop for (var i = 0; i < myarray.length; i++) { // d ...
- JavaScript基础——JavaScript语法基础(笔记)
JavaScript语法基础(笔记) 1.语言编码 JavaScript语言建立在Unicode字符集基础之上,因此脚本中,用户可以使用双字节的字符命名常量.变量或函数等. [示例] var 我=&q ...
- JavaScript基础——JavaScript函数(笔记)
avaScript 函数(笔记) JavaScript 是函数式编程语言,在JavaScript脚本中可以随处看到函数,函数构成了JavaScript源代码的主体. 一.定义函数 定义函数的方法有两种 ...
- JavaScript基础——JavaScript常量和变量(笔记)
JavaScript常量和变量(笔记) Javascript代码严格区分大小写. javascript暂不支持constant关键字,不允许用户自定义常量. javascript使用var关键字声明变 ...
- JavaScript基础JavaScript的常用编码惯例(007)
采用一定的编码惯例,可以使得项目中的代码提到较高的一致性,可读性和可预测性. 1.缩进缩 进可以提高代码的可读性.不过错误的缩进也可能导致代码的误读.有人认为缩进应该使用tab,另外的一些人主张采用4 ...
随机推荐
- Linux以百万兆字节显示内存大小
Linux以百万兆字节显示内存大小 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ free --tera total used free shared buf ...
- java.sql.SQLException:No suitable driver found for http://localhost:3306/school
1.错误描述 java.sql.SQLException:No suitable driver found for http://localhost:3306/school 2.错误原因 Class. ...
- Error:Error #2174
1.错误描述 Error:Error #2174 : 对于每个FileReference,每次只能执行一个下载.上载.加载或保存操作 2.错误原因 Flex中,在做单文件上传时,多次点击"上 ...
- hdu5988 Coding Contest
首先这是个费用流,用log转乘法为加法,外加模板的修改,需加eps 下面是废话,最好别看 闲来无事(鼓起勇气)写这篇博客 这是个自带影像回访的题目 青岛的炼铜之旅,大学的acm生涯就这样结束了.或许还 ...
- freemarker之list遍历(八)
1.设置数据源 /** * * @Title:student * @Description: * @param:@param name * @return: void * @throws */ pri ...
- 手机端仿ios的省市县3级联动脚本一
一,图片实例 二,代码 2.1,代码 $('#provinceCity_fu').click(function(){ var $this = $(this); new Picker({ "t ...
- Java并发编程-各种锁
安全性和活跃度通常相互牵制.我们使用锁来保证线程安全,但是滥用锁可能引起锁顺序死锁.类似地,我们使用线程池和信号量来约束资源的使用, 但是缺不能知晓哪些管辖范围内的活动可能形成的资源死锁.Java应用 ...
- MPTCP iperf 发包方式
之前用的发包方式是发送大文件,用NC监测. 今天改了另外一种发包方式iperf,简单记录下. iperf发包,具体方法: 1.在终端中运行拓扑脚本: 运行py脚本:sudo python topy.p ...
- HandsonTable日期控件的汉化
由于项目的需要,想把HandsonTable自带的日期中英文替换成中文.其实这个不难,只要在库文件中替换下就可以了,替换的效果对比如下: 如果有需要的同学,可以在此处下载 By QJL
- 简单探讨 javascript 闭包
函数作为返回值 高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回. 我们来实现一个对Array的求和.通常情况下,求和的函数是这样定义的: function sum(arr) { ret ...