精华内容
下载资源
问答
  • 以我并不丰富的经验也知道是因为js对象赋值是引用赋值,传递的是地址,所以我改后面的对象会把原对象也改了,于是百度如何完整的复制一个对象用来传递,找到了Object.assign()方法: var newData = Object....

    项目开发中遇到一个问题,需求是复制一条记录,方便编辑,因为前端是根据新建的数据有没有ID来判断走新建还是update接口,于是我在复制按钮的事件中将本条记录的ID删除后传给form。写完后发现点了复制以后原表格中的数据ID也没了,

    QQ截图20201117152544.jpg

    以我并不丰富的经验也知道是因为js的对象赋值是引用赋值,传递的是地址,所以我改后面的对象会把原对象也改了,于是百度如何完整的复制一个对象用来传递,找到了Object.assign()方法:

    var newData = Object.assign({}, data);
    //将data中的可枚举属性复制到{}中,返回给 newData

    当源对象的属性值是一个指向对象的引用时,应用深度复制

    var obj1 = { a: 0 , b: { c: 0}};
    var obj3 = JSON.parse(JSON.stringify(obj1));//先将obj转换为JSON字符串,然后再转回对象
    obj1.a = 4;
    obj1.b.c = 4;
    console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}

     

    展开全文
  • Javascript中的对象拷贝(对象复制) CSDN:jcLee95 邮箱:291148484@163.com 1. 对象的引用 要说“拷贝”还要先说“引用”的概念。 在JavaScript中没有“指针”的概念,但保留了对象的“引用”。首先必须明确,与...
    Javascript中的对象拷贝(对象复制/克隆)

    李俊才
    CSDN:jcLee95
    邮箱:291148484@163.com


    1. 对象的引用

    要说“拷贝”还要先说“引用”的概念。
    在JavaScript中没有“指针”的概念,但保留了对象的“引用”。首先必须明确,与“Java”、“Python”等经典面向对象编程语言中“一切皆可对象”不同,在JavaScript中绝非一切皆是对象,并且“引用”是“对象”的引用。这里就需要区分在赋值操作“=”的右侧,到底是一个“字面量”还是一个对象。举例而言:

    var a = 1;
    var b = "Hello World!"
    
    var c = a
    

    这里的数字1和"Hello World!"都并非对象,而是不可变的字面量值。他们分别源于简单基本类型numberstring而不是内置对象NumberString。(不过,对于左侧的变量,如果你要使用一些方法或属性,如.leng,并不需要显式将string转为String对象)

    由于右侧不是对象,这在赋值操作var c = a传递的是值,即将number 1传给变量c,换成var c = b也类似。

    而下例中:

    var d = {
      Hello : 'world'
    };
    
    var e = d;
    

    由于变量d的右侧是一个变量,这时var d = {Hello : 'world'};使得变量d创建了一个引用,即使得d中保存了右侧那个对象的地址,我们可以对变量d间接对右侧那个变量进行操作,如d.Hello。而后一个赋值操作var e = d;传递的是引用的内容,由于第一个赋值使得d引用到了其右侧那个对象的内存地址,后一个赋值只不过是将变量d中所存储的内容地址赋值了一份给变量e而已,因此这时变量ed引用到了同一个对象。

    2. 浅拷贝

    浅拷贝,又称“浅层拷贝”、“浅复制”、“浅层复制”等等。
    一个很常见的通俗说法,“浅层拷贝就是只拷贝一层”,这样的说法其实不太准确。
    浅拷贝的本质特点是:

    • 拷贝原对象后将得到一个新对象;
    • 新对象的将中的所有属性都是原对象中对应属性的一个引用

    因此从表象上看,浅拷贝拷贝出来的新对象中所有属性的值会复制原对象中对应属性的值。例如:

    var obj_a = {
      is_right : true
    }
    
    var obj_b == {
     a : 1,
     b : obj_a
    }
    

    如果获取对象obj_b的浅拷贝得到一个新对象,可以使用ES6提供的Object.assign()方法:

    var new_obj = Object.assign({}, obj_b);
    

    其中Object.assign()方法,第一个参数是目标对象,后面为一个或多个源对象。
    该方法对obj_b实现浅拷贝的过程为,遍历一个或多个源对象(从第二个参数开始)所有可枚举的自有键,并逐个进行“=”完成复制,最后返回目标对象。
    上例中,对于键值对“a:1”,由于数字“1”是一个不可变的值(字面量)而非数字,new_obj的第一个键值对完全相同,故有:

    new_obj.a == 1   // true
    

    然而第二个键值对的值obj_a引用了一个对象,进行“=”复制到new_obj的键值时,传递的时引用的地址,这样使得new_obj对应与键b的值引用到了对象obj_a。即必有:

    new_obj.b === obj_a
    

    那么,为什么称浅层拷贝呢?
    以上我们已经了解了这种拷贝方法的本质,但是如果想要了解这个名字的由来,我们不妨假设上例中,将obj_a修改为一个键值中含有对象的对象。如:

    var obj_c = {
    are_you_ok : true
    }
    
    var obj_a = {
      is_right : true,
      is_ok : obj_c
    }
    
    var obj_b == {
     a : 1,
     b : obj_a
    }
    

    这时对 obj_b 进行浅拷贝得到new_obj后,new_obj.is_ok对应的值为由obj_a.is_ok对应的值obj_c。由于变量obj_c中存储的是对一个对象的引用,这里传递的同样是被引用对象的地址,但地址中所存储的呢欧容不会进一步拷贝,这样在new_obj中,并不会存储一个

    {are_you_ok : true}
    

    这样的实际对象。因此看起来我们“只拷贝了表层”。这就是所谓“浅”拷贝称为的由来。

    这里最后还有一个需要注意的问题,使用Object.assign()方法浅拷贝时由于相当于只是对源对象的所有可枚举的自有键一一进行“=”赋值操作,对于由属性描述符所描述的一些属性的特性是不会被拷贝到目标对象的。如某个属性是否可修改(Writeable)、可配置(Configurable)、可枚举(Enumerable)

    3. 深拷贝

    在JavaScript中,深拷贝说起来有点麻烦,因为里面情况会很比较复杂。
    相比于浅拷贝深拷贝要求要完整地拷贝下底层被引用地对象而不是仅粗略地要求拷贝下引用中对象的地址。正如之前所说通俗一点理解看:

    • 仅用"="将对象引用的赋值给变量时,仅传递了引用的对象地址;
    • 通过“浅拷贝”返回对象时,相当于对源对象最外层的所有可枚举属性进行了“=”操作后获得的新对象;
    • 通过“深拷贝”返回对象时,相当于任意一层不再简单传递引用的对象的内存地址,而是真正意义上拷贝下来每一层对象。

    但是很快你就会发现,如果在一个对象中引用的对象到某层由存在循环性的引用,往往会导致一个死循环。
    另外,在JavaScript中的函数也是对象,我们在JS中不能确定对一个函数进行“深拷贝”是什么,尽管由很多框架给出了自己的定义。

    一种比较好方法是通过JSON序列化来实现深拷贝:

    var obj_b = JSON.parse(JSON.stringify(obj_a))
    

    这种方法也不是万能的,它要求对象必须是JSON安全的,即:
    不仅obj_a可以被序列化为一个JSON格式的字符串,同时还可以由该字符串解析得到一个结构完全相同的对象。

    展开全文
  • JS复制对象

    2021-04-01 11:34:21
    在这篇文章中,我将会讲到几种在JS复制对象的方式,我们将会关注到浅复制和深复制。 在开始之前,值得一提的是一些基础知识:JS中的对象只是对内存中某个位置的引用。这些引用是可以更改的。即他们可以被重新分配...

    原文地址:Copying objects in Javascript, 原文作者:Victor Parmar
    渣翻译,有英文阅读能力的可以去原网址阅读,正文部分的括号内是译者的尝试补充说明
    自豪地采用谷歌翻译

    转载:张子虚的博客:https://blog.csdn.net/ccaoee/article/details/86510718

     

    在这篇文章中,我将会讲到几种在JS中复制对象的方式,我们将会关注到浅复制和深复制。
    在开始之前,值得一提的是一些基础知识:JS中的对象只是对内存中某个位置的引用。这些引用是可以更改的。即他们可以被重新分配。从而,简单的复制引用的操作在结果上仅仅是将两个引用指向了内存中的同一位置。

    var foo = {
      a: 'abc'
    }
    console.log(foo.a) // abc
    
    var bar = foo
    console.log(bar.a) // abc
    
    foo.a = 'yo foo'
    console.log(foo.a) // yo foo
    console.log(bar.a) // yo foo
    
    bar.a = 'whatup bar?'
    console.log(foo.a) // whatup bar?
    console.log(bar.a) // whatup bar?
    

    正如你从上面例子中看到的,foo和bar都反映了同一个对象的变化。从而,在JS中复制对象需要小心,具体取决于您的用例。

    浅复制

    如果你的对象的属性的类型仅仅只是值类型(译者注:基本类型)的。你可以使用扩展运算符语法或者Object.assign(...)

    var obj = { foo: 'foo', bar: 'bar' }
    var copy = { ...obj } // Object { foo: 'foo', bar: 'bar' }
    
    var obj = { foo: 'foo', bar: 'bar' }
    var copy = Object.assign({}, obj) // Object { foo: 'foo', bar: 'bar' }
    

    请注意,上述两种方法都可用于将属性值从多个源对象复制到目标对象:

    var obj1 = { foo: 'foo' }
    var obj2 = { bar: 'bar' }
    
    var copySpread = { ...obj1, ...obj2 } // Object { foo: 'foo', bar: 'bar' }
    var copyAssign = Object.assign({}, obj1, obj2) // Object { foo: 'foo', bar: 'bar' }
    

    事实上,上述方法的问题在于对象的属性如果是一个对象,则只会复制该属性对象在内存中的引用。即它相当于var bar = foo,如同第一个代码例子:

    var foo = { a: 0, b: { c: 0 } }
    var copy = { ...foo }
    
    copy.a = 1
    copyb.c. = 2
    
    console.dir(foo) // { a: 0, b: { c: 2 } }
    console.dir(copy) // { a: 0, b: { c: 2 } }
    

    深复制(有缺陷)

    为了对对象进行深复制操作,一个潜在的解决方案是序列化对象为一个字符串,然后反序列化,生成一个新对象:

    var obj = { a: 0, b: { c: 0 } }
    var copy = JSON.parse(JSON.stringify(obj))
    

    不幸的是,这个方法仅仅适用于当源对象包含可序列化的值类型并且没有循环引用的情况。不能序列化的值的类型,比如Date对象,即使它在字符串化上以ISO格式打印。JSON.parse仅仅会将它解释为一个字符串,而不是Date对象。

    深复制(更少的缺陷)

    对于更复杂的对象,可以使用更新的HTML5structured clone克隆算法。不幸的是,在撰写本文时,它仍局限于某些内置类型,但它支持的内容类型比JSON.parse更多。比如:DateRegExpMapSetBlobFileListImageData、稀疏和类型化数组。它还在克隆对象中保留了引用关系。允许它支持不适用于上述序列化方法的循环和递归结构。

    当前还没有直接调用结构化克隆算法的方法,但一些新的浏览器特性可以被用来间接使用这个方法。从而,我们会得到一些可能用于深度复制对象的变通方法

    使用 MessageChannel:这背后的想法是利用MessageChannel通信功能使用的序列化算法。这个功能是基于事件的,因此获取克隆结果是一个异步的操作。

    class StructruedCloner {
      constructor() {
        this.pendingClones_ = new Map()
        this.nextKey_ = 0
        
        const channel = new MessageChannel()
        this.inPort_ = channle.port1
        this.outPort_ = channel.port2
        
        this.outPort_.onmessage = ({data: {key, value}}) => {
          const resolve = this.pendingClones_.get(key)
          resolve(value)
          this.pendingClones_.delete(key)
        }
        this.outPort_.start()
      }
      
      cloneAsync(value) {
        return new Promise(resolve => {
          const key = this.nextKey_++
          this.pendingClones_.set(key, resolve)
          this.inPort_.postMessage({key, value})
        })
      }
    }
    
    const structuredCloneAsync = window.structuredCloneAsync = 
          StructuredCloner.prototype.cloneAsync.bind(new StructuredCloner)
    
    const main = async () => {
      const original = { date: new Date(), number: Math.random() } // 译者注释:添加一些JSON方法不能解释的对象
      original.self = original // 译者注释:添加循环引用
      
      const clone = await structuredCloneAsync(original)
      
      // 不同的对象
      console.assert(original !== clone)
      console.assert(original.date !== clone.date)
      
      // 循环
      console.assert(original.self === original)
      console.assert(clone.self === clone)
      
      // 等价值
      console.assert(original.number === clone.number)
      console.assert(Number(original.date) === Number(clone.date))
      
      console.log('Assertions complete.')
    }
    
    main()
    

    使用historyAPIhistory.pushState()history.replaceState()两个方法会创建它们第一个参数的结构化对象。注意这个方法是同步的,操纵浏览器历史记录不是一个快速的操作并且反复调用此方法可能导致浏览器无响应。

    const structureClone = obj => {
      const oldState = history.state
      history.replaceState(obj.null)
      const clonedObj = history.state
      history.replaceState(oldState, null)
      return clonedObj
    }
    

    使用notificationAPI:当创建一个新的提醒(译者注:notification),构造函数会从它所关联的数据中创建一份结构化的克隆副本。注意,这么做浏览器会尝试将提醒显示给用户。但是这将会静默失败。除非应用已经请求到显示提醒的权限。万一权限存在,提醒会立即关闭。

    const structuredClone = obj => {
      const n = new Notification('', {data: obj, silent: true})
      n.onshow = n.close.bind(n)
      return n.data
    }
    

    在NodeJS中进行深复制

    在NodeJS的8.0.0版本中,它提供了一个序列化的API,它是兼容结构化克隆的。注意:这个API在本文撰写时(译者注:原文发表于2018.11.1)还是标记为实验性的:

    const v8 = require('v8')
    const buf = v8.serialize({a: 'foo', b: new Date()})
    const cloned = v8.deserialize(buf)
    cloned.b.getMonth()
    

    对于版本低于8.0.0或者更稳定的实现,一种方法是:可以使用lodashcloneDeep方法。该方法也基于结构化克隆算法

    结论

    总而言之,在JS中复制对象最佳的算法是严重依赖于你所复制对象的上下文和类型的。而lodash是通用深复制函数最安全的选择。也许你会给出更高效的实现呢。下面是一个对Date对象也起效的深复制的函数:

    function deepClone(obj) {
      var copy
      
      // 处理3种基础类型,和null、undefined
      if (obj === null || typeof obj !== 'object') return obj
      
      // 处理日期
      if (obj instanceof Date) {
        copy = new Date()
        copy.setTime(obj.getTime())
        return copy
      }
      
      // 处理数组
      if (Array instanceof Array) {
        copy = []
        for (var i = 0, len = obj.length; i < len; i++) {
          copy[i] = deepClone(obj[i])
        }
        return copy
      }
      
      // 处理函数
      if (obj instanceof Function) {
        copy = function() {
          return obj.apply(this, arguemnts)
        }
        return copy
      }
      
      // 处理对象
      if (obj instance Object) {
        copy = {}
        for (var attr in obj) {
          if (obj.hasOwnProperty(attr)) copy[attr] = deepClone(obj[attr])
        }
        return copy
      }
      
      throw new Error("Unable to copy obj as type isn't suported" + obj.constructor.name)
    }
    

    个人而言,我期待能够在任何地方使用结构化克隆,最后让这个问题得到休息,快乐的克隆:)

    展开全文
  • 在项目中使用一个对象,但是这个对象里面修改一些属性的话会造成之前的数据的一些错误,所以我决定深度克隆一些,但是现在谁还自己写呀,所以我果断使用插件, 使用了插件的我,腰也不疼了,腿也不酸了,真香,但是...

    在项目中使用一个对象,但是这个对象里面修改一些属性的话会造成之前的数据的一些错误,所以我决定深度克隆一些,但是现在谁还自己写呀,所以我果断使用插件,在这里插入图片描述
    使用了插件的我,腰也不疼了,腿也不酸了,真香,但是使用完之后我深深的陷入了悔恨,咋这么不争气那,不会自己写一个啊,人与人之间的距离就是这样拉开的,我是开车的,人家是造车的。555555555555555555!!!
    所以我决定要自己 写一段代码

    function deepClone ( obj )    {  
       let  clone =  Array.isArray( obj ) ? [ ] :  { } 
         if (  obj   &&  typeOf   obj   ===  'object'  )  { 
          for (  key in  obj ) { 
           if  ( obj.hasOwnProperty(key) )   { 
              if ( obj[key]  &&  typeof obj[key]  === 'object' ){ 
                  	clone[key] = deepClone(obj[key])
              }else {
                    clone[key] = obj[key]
              }
           }
         } 
      }
       return clone
    }
    

    但是这个克隆方法还是有缺陷的 像函数 ,正则 ,时间 都克隆不了,还是比较不完善的,但是它解决了普通的对象深克隆 。
    还有JSON.parse(JSON.stringify(obj)) 也可以深度克隆 ,但是有缺陷,判断函数,NaN ,正则都会出一些问题

    展开全文
  • 1.通用对象克隆: function clone(obj){ let temp = null; if(obj instanceof Array){ temp = obj.concat(); }else if(obj instanceof Function){ //函数是共享的是无所谓的,js也没有什么办法可以在定义后再...
  • 2.如果是对象,建议自己封装一个函数,变量原对象,将遍历结果赋值给新建对象 function newobj(obj1) { if (obj1 instanceof Object) { var obj2 = { } var shuxing = "" for (o in obj1) {
  • [js] 请写一个性能最好的深度克隆对象的方法 const deepClone = (obj) => { const copy = obj instance Array ? [] : {}; for (let key in obj) { if (obj.hasOwnProperty(key)) { copy[key] = typeof obj...
  • function copy(o){ if(typeof (o)===typeof(1)||typeof('')=== typeof(o)||typeof (o)===typeof(true)|| typeof(o)===typeof(undefined)){ return o } if(Array.isArray(o)){ let arr=[] ...
  • var obj = { a: 1, b: 2, c: 3, d: 4, e: 5 } 如果只需要里面的 a b c 属性 var {a, b , c} = obj var obj2 = {a, b , c} var obj = { a: 1, b: 2, c: 3, d: 4, ...const obj2 = (({.
  • js去除对象属性的空值 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <...
  • 对象通用克隆方法 先将对象序列化再解析回来,不过要注意对象中如果有函数function则不能正确复制,如下: var obj = {a:1, b:2} var newObj = JSON.parse(JSON.stringify(obj)); 通用方法,就是写一个对象拷贝...
  • //自定义深度复制对象or数组 let copyObjOrArr = o => { let isArray = o instanceof Array; let isObject = o instanceof Object; if (!isObject) return o; let n = (isArray ? [] : {}); for (let k in ...
  • 对象的深拷贝与浅拷贝的区别如下:浅拷贝:仅仅复制对象的引用,而不是对象本身;深拷贝:把复制的对象所引用的全部对象都复制一遍。一. 浅拷贝的实现浅拷贝的实现方法比较简单,只要使用是简单的复制语句即可。1.1 ...
  • js对象连续结构复制

    2021-01-21 20:48:21
    Document
  • js面向对象对象深浅克隆 认识对象:键值对的集合 访问属性:打点或方括号,推荐使用方括号 修改、添加属性:对象.属性=XXX 删除属性:delete 对象.属性 对象的方法:对象的某个属性值是方法,则其也称为对象的方法...
  • js对象复制

    2021-07-27 20:14:15
    当复杂数据类型如Object与Array存储的时候,是...浅复制:是指以目标对象的引用地址赋值给一个新的对象,既两个对象有相同的引用地址,那么自然就有相同的实例.新对象在发生改变的时候,原对象也自然随之改变. 浅复制不会复
  • JavaScript中的对象复制

    2021-03-05 10:57:15
    所有的面向对象的语言中,都存在着对象引用、复制等等问题,对于初学者来说可能难以理解。今天我来总结一下JavaScript对象复制。...在js中对对象进行赋值时,基本类型会被直接复制,例如下: let a = 1;
  • 平时我们在处理纯粹对象(键值对对象/JSON)时,如果使用Object.assign或者对象解构赋值,只会合并第一层的数据,而当合并嵌套对象,将会直接覆盖掉前面被合并对象里的数据,这是因为Object.assign和对象解构赋值都...
  • ES6 Object对象的新增方法 Object.is() ...Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。 const target = { a: 1 }; const source1 = { b: 2 }
  • 创建对象 通常使用字面量创建 let obj1 = {username: 'smyhvae', age: 26}; 遍历对象 for in var obj = { name: "smyhvae", age: 26, gender: "男", address: "shenzhen" }; //枚举对象中的属性 for ...
  • function clone (Obj) { var buf; if (Obj instanceof Array) { buf = []; //创建一个空的数组 var i = Obj.length; while (i--) { buf[i] = clone(Obj[i]);... } else if (Obj ... //创建一个空对象 for
  • js将一些复杂的方法封装成对象,我们在使用时可以直接调用 常见的内置对象有:Array对象、Date对象、正则表达式对象、string对象、Global对象 、Math对象等 提示:了解更多可以去看MDN文档,JavaScript | MDN ...
  • 我正在尝试克隆元素的样式对象。这应该允许我在更改后重置所述元素的样式。例如:el.style.left; // 50pxcurr_style.left; // 50px;/*Modify the elements style.The cloned style should still hold the original ...
  • js对象转换为html

    2021-06-24 07:26:33
    好的,我有一些JS通过URL从JSON中提取数据。 我知道想要将每个对象(author_...将js对象转换为html例如这是我的JS代码到目前为止function initMap() {var service = new google.maps.places.PlacesService(map);serv...
  • 对象引用和复制 let message = "Hello!"; let phrase = message; 我们可以通过其中任意一个变量来访问该对象并修改它的内容 let user = { name: 'John' }; let admin = user; admin.name = 'Pete'; // 通过 ...
  • // Mick JSON.parse(json.stringify()) clonedPersons = JSON.parse(json.stringify(persons))克隆对象,但删除函数. persons.mItems[0].calculateScore(); // Does not exists !!! 谢谢您的回答. 解决方法: 如果要...
  • js 深度克隆对象

    2021-01-04 15:56:25
    这是一个简单的递归函数:只要是一个对象,就使用函数的构造器将其重新初始化为一个克隆,然后对所有属性重复该过程。 const deepClone = obj => { let clone = obj; if (obj && typeof obj === ...
  • 原生对象分为两类:原始类型和对象类型,原始类型又分为两类,一类是空值,一类是包装对象对象类型也可以分为两类,一类是构造器对象,一类是单体内置对象。ECMA-262 把原生对象(native object)定义为“独立于宿主...
  • 1、本地得克隆方法 //克隆复制数据 function cloneData(val) { return JSON.parse(JSON.stringify(val)); }; 解决办法就是把你当前操作的这个对象克隆一份,
  • js函数传递对象参数

    2021-06-03 07:17:22
    一、在 javascript 中数据类型可以分为两类:原始数据类型值 primitive type,如Undefined,Null,Boolean,Number,String。引用类型值,也就是对象类型 Object type,如Object,Array,Function,Date等。二、声明变量时...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 220,322
精华内容 88,128
关键字:

js克隆对象