- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
在JS中,想要对某一个对象(引用类型)进行一次简单的深拷贝,可以使用JSON提供给我们的两个方法。
JSON.stringfy()
:可以将JavaScript类型转成对应的JSON字符串;JSON.parse()
:可以解析JSON,将其转回对应的JavaScript类型;具体深拷贝的实现:
const obj = {
name: 'curry',
age: 30,
friends: ['kobe', 'klay'],
playBall() {
console.log('Curry is playing basketball.')
}
}
const newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
打印结果:
JSON序列化实现深拷贝的优缺点:
obj
的方法属性并没有被拷贝到newObj
中;既然上面的方法不能满足我们的需求,那么就自己来一步步实现一个深拷贝函数吧。
isObject
,用于判断传入数据是否是对象类型;function isObject(value) {
const valueType = typeof value
// 值不能为null,并且为对象或者函数类型
return (value !== null) && (valueType === 'object' || valueType === 'function')
}
function deepClone(originValue) {
// 判断传入的是否是对象类型,如果不是,说明是普通类型的值,直接返回即可
if (!isObject(originValue)) {
return originValue
}
const newObj = {} // 定义一个空对象
// 循环遍历对象,取出key和值存放到空对象中
// 注意:for...in遍历对象会将其继承的属性也遍历出来,所以需要加hasOwnProperty进行判断是否是自身的属性
for (const key in originValue) {
if (originValue.hasOwnProperty(key)) {
// 递归调用deepClone,如果对象属性值中还包含对象,就会再次进行拷贝处理
newObj[key] = deepClone(originValue[key])
}
}
// 深拷贝完成,将得到新对象返回
return newObj
}
简单测试一下:
const obj = {
name: 'curry',
age: 30,
friends: {
name: 'klay',
age: 11
}
}
const newObj = deepClone(obj)
console.log(newObj)
console.log(newObj.friends === obj.friends)
打印结果:
function deepClone(originValue) {
// 1.判断传入的是否是一个函数类型
if (typeof originValue === 'function') {
// 将函数直接返回即可
return originValue
}
// 2.判断传入的是否是一个Map类型
if (originValue instanceof Map) {
return new Map([...originValue])
}
// 3.判断传入的是否是一个Set类型
if (originValue instanceof Set) {
return new Set([...originValue])
}
// 4.判断传入的值是否是一个Symbol类型
if (typeof originValue === 'symbol') {
// 返回一个新的Symbol,并且将其描述传递过去
return Symbol(originValue.description)
}
// 5.判断传入的值是否是一个undefined
if (typeof originValue === 'undefined') {
return undefined
}
// 6.判断传入的是否是对象类型,如果不是,说明是普通类型的值,直接返回即可
if (!isObject(originValue)) {
return originValue
}
// 7.定义一个变量,如果传入的是数组就定义为一个数组
const newValue = Array.isArray(originValue) ? [] : {}
// 8.循环遍历,如果是对象,就取出key和值存放到空对象中,如果是数组,就去除下标和元素放到空数组中
// 注意:for...in遍历对象会将其继承的属性也遍历出来,所以需要加hasOwnProperty进行判断是否是自身的属性
for (const key in originValue) {
if (originValue.hasOwnProperty(key)) {
// 递归调用deepClone,如果对象属性值中还包含对象,就会再次进行拷贝处理
newValue[key] = deepClone(originValue[key])
}
}
// 9.对key为Symbol类型的情况进行处理
// 拿到所有为Symbol类型的key
const symbolKeys = Object.getOwnPropertySymbols(originValue)
// for...of遍历取出所有的key,存放到新对象中
for (const sKey of symbolKeys) {
newValue[sKey] = deepClone(originValue[sKey])
}
// 10.深拷贝完成,将得到新对象返回
return newValue
}
简单测试一下:
const s1 = Symbol('aaa')
const s2 = Symbol('bbb')
const obj = {
name: 'curry',
age: undefined,
friends: {
name: 'klay',
age: 11
},
hobbies: ['篮球', '足球', '高尔夫'],
map: new Map([[1, 'aaa'], [2, 'bbb'], [3, 'ccc']]),
set: new Set([1, 2, 3]),
s: s1,
[s2]: 'abc'
}
const newObj = deepClone(obj)
console.log(newObj)
打印结果:
我们自定义深拷贝的函数是通过递归来实现的,如果对象中有一个属性值指向了自己,那么在进行深拷贝时会陷入无限循环,这种情况也就是循环引用。
如果没有处理循环引用,那么就会不断递归,最终报错栈溢出:
function deepClone(originValue, wMap = new WeakMap()) {
// 1.判断传入的是否是一个函数类型
if (typeof originValue === 'function') {
// 将函数直接返回即可
return originValue
}
// 2.判断传入的是否是一个Map类型
if (originValue instanceof Map) {
return new Map([...originValue])
}
// 3.判断传入的是否是一个Set类型
if (originValue instanceof Set) {
return new Set([...originValue])
}
// 4.判断传入的值是否是一个Symbol类型
if (typeof originValue === 'symbol') {
// 返回一个新的Symbol,并且将其描述传递过去
return Symbol(originValue.description)
}
// 5.判断传入的值是否是一个undefined
if (typeof originValue === 'undefined') {
return undefined
}
// 6.判断传入的是否是对象类型,如果不是,说明是普通类型的值,直接返回即可
if (!isObject(originValue)) {
return originValue
}
// 循环引用处理:判断wMap中是否存在原对象,如果存在就取出原对象对应的新对象返回
if (wMap.has(originValue)) {
return wMap.get(originValue)
}
// 7.定义一个变量,如果传入的是数组就定义为一个数组
const newValue = Array.isArray(originValue) ? [] : {}
// 循环引用处理:将原对象作为key,新对象作为value,存入wMap中
wMap.set(originValue, newValue)
// 8.循环遍历,如果是对象,就取出key和值存放到空对象中,如果是数组,就去除下标和元素放到空数组中
// 注意:for...in遍历对象会将其继承的属性也遍历出来,所以需要加hasOwnProperty进行判断是否是自身的属性
for (const key in originValue) {
if (originValue.hasOwnProperty(key)) {
// 递归调用deepClone,如果对象属性值中还包含对象,就会再次进行拷贝处理
newValue[key] = deepClone(originValue[key], wMap)
}
}
// 9.对key为Symbol类型的情况进行处理
// 拿到所有为Symbol类型的key
const symbolKeys = Object.getOwnPropertySymbols(originValue)
// for...of遍历取出所有的key,存放到新对象中
for (const sKey of symbolKeys) {
newValue[sKey] = deepClone(originValue[sKey], wMap)
}
// 10.深拷贝完成,将得到新对象返回
return newValue
}
简单测试一下:
const s1 = Symbol('aaa')
const s2 = Symbol('bbb')
const obj = {
name: 'curry',
age: undefined,
friends: {
name: 'klay',
age: 11
},
hobbies: ['篮球', '足球', '高尔夫'],
map: new Map([[1, 'aaa'], [2, 'bbb'], [3, 'ccc']]),
set: new Set([1, 2, 3]),
s: s1,
[s2]: 'abc'
}
// 循环引用
obj.self = obj
const newObj = deepClone(obj)
console.log(newObj)
console.log(newObj.self.self.self.self)
打印结果:
我正在学习构建单页应用程序 (SPA) 所需的所有技术。总而言之,我想将我的应用程序实现为单独的层,其中前端仅使用 API Web 服务(json 通过 socket.io)与后端通信。前端基本上是
当我看到存储在我的数据库中的日期时。 这是 正常 。日期和时间就是这样。 但是当我运行 get 请求来获取数据时。 此格式与存储在数据库 中的格式不同。为什么会发生这种情况? 最佳答案 我认为您可以将
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在尝试使用backbone.js 实现一些代码 和 hogan.js (http://twitter.github.com/hogan.js/) Hogan.js was developed ag
我正在使用 Backbone.js、Node.js 和 Express.js 制作一个 Web 应用程序,并且想要添加用户功能(登录、注销、配置文件、显示内容与该用户相关)。我打算使用 Passpor
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 8 年前。 Improve this ques
我尝试在 NodeJS 中加载数据,然后将其传递给 ExpressJS 以在浏览器中呈现 d3 图表。 我知道我可以通过这种方式加载数据 - https://github.com/mbostock/q
在 node.js 中,我似乎遇到了相同的 3 个文件名来描述应用程序的主要入口点: 使用 express-generator 包时,会创建一个 app.js 文件作为生成应用的主要入口点。 通过 n
最近,我有机会观看了 john papa 关于构建单页应用程序的精彩类(class)。我会喜欢的。它涉及服务器端和客户端应用程序的方方面面。 我更喜欢客户端。在他的实现过程中,papa先生在客户端有类
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我是一个图形新手,需要帮助了解各种 javascript 2D 库的功能。 . . 我从 Pixi.js 中得到了什么,而我没有从 Konva 等基于 Canvas 的库中得到什么? 我从 Konva
我正在尝试将一些 LESS 代码(通过 ember-cli-less)构建到 CSS 文件中。 1) https://almsaeedstudio.com/ AdminLTE LESS 文件2) Bo
尝试查看 Express Passport 中所有登录用户的所有 session ,并希望能够查看当前登录的用户。最好和最快的方法是什么? 我在想也许我可以在登录时执行此操作并将用户模型数据库“在线”
我有一个 React 应用程序,但我需要在组件加载完成后运行一些客户端 js。一旦渲染函数完成并加载,运行与 DOM 交互的 js 的最佳方式是什么,例如 $('div').mixItUp() 。对
请告诉我如何使用bodyparser.raw()将文件上传到express.js服务器 客户端 // ... onFilePicked(file) { const url = 'upload/a
我正在尝试从 Grunt 迁移到 Gulp。这个项目在 Grunt 下运行得很好,所以我一定是在 Gulp 中做错了什么。 除脚本外,所有其他任务均有效。我现在厌倦了添加和注释部分。 我不断收到与意外
我正在尝试更改我的网站名称。找不到可以设置标题或应用程序名称的位置。 最佳答案 您可以在 config/ 目录中创建任何文件,例如 config/app.js 包含如下内容: module.expor
经过多年的服务器端 PHP/MySQL 开发,我正在尝试探索用于构建现代 Web 应用程序的新技术。 我正在尝试对所有 JavaScript 内容进行排序,如果我理解得很好,一个有效的解决方案可以是服
我是 Nodejs 的新手。我在 route 目录中有一个 app.js 和一个 index.js。我有一个 app.use(multer....)。我还定义了 app.post('filter-re
我正在使用 angular-seed用于构建我的应用程序的模板。最初,我将所有 JavaScript 代码放入一个文件 main.js。该文件包含我的模块声明、 Controller 、指令、过滤器和
我是一名优秀的程序员,十分优秀!