使用js实现复制功能

 更新时间:2022年08月23日 10:38:42   作者:@Junean  
这篇文章主要为大家详细介绍了使用js实现复制功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了使用js实现复制功能的具体代码,供大家参考,具体内容如下

复制

1.遍历复制(for in)

特征:不修改引用关系(原来的属性还在),仅能复制字符属性,Symbol不能复制,不可枚举属性不能复制,原型链不能复制。浅复制

2.JOSN.parse(JSON.stringify(obj)) 转换复制

特征:修改引用关系(相当于创建一个新的对象,不再拥有原来的属性),仅能复制字符属性,Symbol不能复制,不可枚举属性不能复制,原型链不能复制,函数和其他类型不能复制。深复制

3.{…obj}解构赋值复制

特征:修改引用关系,Symbol和函数都能复制,不可枚举属性和原型链都不能复制。浅复制

4.Object.assign()对象复制

特征:不修改引用关系,可以复制属性、方法、Symbol类型,不可枚举属性和原型链都不能复制。浅复制

深复制**

1.使用defineProperty***

function cloneObject(source,target){
    if(source === null||source === undefined) return source;
    if(source===document) return;
    //判断target是不是继承对象的实例,是不是引用类型(null,undefined,Boolean,string,number都不是引用类型)
    if(!Object.prototype.isPrototypeOf(target)){
        //判断源对象是不是dom元素
        if(HTMLElement.prototype.isPrototypeOf(source)){
            //创建dom元素
             target = document.createElement(source.nodeName);
        }else if(source.constructor === RegExp){
            // 任何正则表达式都有source和flags,source是正则内容,flags是正则修饰符
            // 因为这两个属性都是只读属性,不能写入,必须通过构造函数创建时带入
            target = new RegExp(source.source,source.flags);
        }else if(source.constructor === Date){
            // 日期对象在创建的对象中将原有的日期对象放入,可以让当前日期对象变为原有日期对象的值,但是没有引用关系
            targer = new Date(source);
        }else if(source.constructor === Function){
            // 复制函数,通过正则表达式将函数中的参数以及函数体内容提取到数组中,然后通过new Function()创建
            var arr = source.toString().replace(/\n|\r/g,"").trim().match(/\((.*?)\)\s*\{(.*)\}/).slice(1);
            target = new Function(arr[0].trim(),arr[1]);
        }else if(source.constructor === Set){
            // set类型,在处理时,new Set时可以带入数组,因此我们将原有set的列表强转为数组,并且将这个强转后的数组复制给新数组
            target = new Set(cloneObject(Array.from(source.values())));
        }else if(source.constructor === Map){
            target = new Map();
            // 如果是map类型,遍历map中每个元素
            for(var [key,value] of source.entries()){
                // 如果key是引用类型,
                if(Object.prototype.isPrototypeOf(key)){
                     // 如果value引用类型,则将key和value分别做复制,并且将返回的结果放在map中
                    if(Object.prototype.isPrototypeOf(value)){
                        target.set(cloneObject(key),cloneObject(value));
                    }else{
                         //如果value不是引用类型,只将key复制,并且放入map
                        target.set(cloneObject(key),value);
                    }
                }else{
                    // 这是key不是引用类型时
                    if(Object.prototype.isPrototyeOf(value)){
                        target.set(key,cloneObject(value));
                    }else{
                        target.set(key,value);
                    }
                }
            }
        }
        else{
        //除了null和undefined,其他类型都有constructor。任何对象的constructor都是它的类型,利用其constructor创建对象
        //通过对象类型的反射创建新的同类型对象
            target = new source.constructor();
        }
        
    }
    //获取对象的所有字符属性名和Symbol属性名的数组
    var names = Object.getOwnPropertyName(source).concat(Object.getOwnPropertySymbols(source));
    for(var i = 0;i < names.lenght; i++){
        // 如果当前复制的是函数,并且这个函数的属性是prototype,那么这个属性不复制,否则会死循环
        if(source.constructor === Function&&names[i] === "prototype")
            continue;
        // 获取当前属性名的描述对象
        var desc = Object.getOwnPropertyDescriptor(source,names[i]);
        //   这个描述对象的值如果是引用类型
        if(Object.prototype.isPrototypeOf(desc.value)){
             // 根据需要将源对象的描述内容设置给当前目标对象相同属性名的描述内容,及值付为刚才创建相同类型的对象
            Object.defineProperty(target,names[i],{
                enumerable:desc.enumerable,
                configurable:desc.configurable,
                writable:desc.writable,
                value:cloneObject(desc.value)
            });
        }else{
             //如果描述的对象的值不是引用类型,直接将描述对象设置给目标对象的这个属性
            Object.defineProperty(target,names.desc);
        }
    }
    return target;
}


//原型.isPrototypeOf(对象)。对象里面是不是拥有xx的原型
//反射:通过对象

2.使用JSON对象实现深复制

使用**JSON.parse(str)**可以将字符串转换成对象;

使用**JSON.stringify(obj)**将对象转换成对象形式的字符串,其中无法转换对象中的方法,可以考虑先将对象中的方法使用toString()转为字符串,然后再转换使用JSON.stringify(obj);

*使用**JSON.parse(str)**可以将字符串转换成对象

var obj={
    a:1,
    b:3,    //ab复制不会随其中一个的变化而变化
    c:{        //c复制会随其中一个的变化而变化,因为c属于对象的地址引用关系
        d:10,
        e:20
    }
};
var o1 = JSON.parse(JSON.stringify(obj)); //将obj复制给o1

3.使用递归实现深复制

结构仅限于对象。如果存在数组、正则、日期对象、dom对象则不能使用。

var obj = {
a:1,
b:2,
c:{
        a:1,
  b:2,
  c:{
            a:1,
      b:2,
      }
}
}
//函数定义参数时,注意必要参数写在前面,非必要参数写在后面
function cloneObj(source,target){
    if(target === undefined) target = {};
for(var prop in source){
  //如果
        if(typeof source[prop] === "object" && source[prop] != null){
      target[prop] = {};
      cloneObj(source[prop],target[prop]);
  }else{
            target[prop] = source[prop];
  }
}
return target;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • localResizeIMG先压缩后使用ajax无刷新上传(移动端)

    localResizeIMG先压缩后使用ajax无刷新上传(移动端)

    随着技术的发展,移动设备像素越来越高,但是这么大的图片怎么上传呢?下面小编就给大家一起学习移动端图片上传的方法之localResizeIMG先压缩后使用ajax无刷新上传,需要的朋友可以参考下
    2015-08-08
  • 使用JS实现图片轮播的实例(前后首尾相接)

    使用JS实现图片轮播的实例(前后首尾相接)

    下面小编就为大家带来一篇使用JS实现图片轮播的实例(前后首尾相接)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-09-09
  • 整理Javascript基础语法学习笔记

    整理Javascript基础语法学习笔记

    整理Javascript基础语法学习笔记,之前一系列的文章是跟我学习Javascript,本文就是进一步学习javascript基础语法,希望大家继续关注
    2015-11-11
  • javascript使用appendChild追加节点实例

    javascript使用appendChild追加节点实例

    这篇文章主要介绍了javascript使用appendChild追加节点的方法,实例分析了appendChild()函数增加结点的使用技巧,需要的朋友可以参考下
    2015-01-01
  • JavaScript前后端JSON使用方法教程

    JavaScript前后端JSON使用方法教程

    这篇文章主要给大家介绍了关于JavaScript前后端JSON使用方法的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Javascript 数组添加 shuffle 方法的实现代码

    Javascript 数组添加 shuffle 方法的实现代码

    PHP 里面有个非常方便的打乱数组的函数 shuffle() ,这个功能在许多情况下都会用到,但 javascript 的数组却没有这个方法,没有不要紧,可以扩展一个,自己动手,丰衣足食嘛。
    2009-09-09
  • javascript实现编写网页版计算器

    javascript实现编写网页版计算器

    这篇文章主要为大家详细介绍了javascript实现编写网页版计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • JavaScript实现单击网页任意位置打开新窗口与关闭窗口的方法

    JavaScript实现单击网页任意位置打开新窗口与关闭窗口的方法

    这篇文章主要介绍了JavaScript实现单击网页任意位置打开新窗口与关闭窗口的方法,涉及javascript窗口的相关操作函数与使用技巧,需要的朋友可以参考下
    2017-09-09
  • PixiJS学习之如何实现文字的绘制

    PixiJS学习之如何实现文字的绘制

    PixiJS是一个开源的基于web的渲染系统,为游戏、数据可视化和其他图形密集型项目提供了极快的性能。这篇文章主要带大家学习一下PixiJS是如何实现文字绘制的,希望对大家有所帮助
    2023-02-02
  • 关于数据与后端进行交流匹配(点亮星星)

    关于数据与后端进行交流匹配(点亮星星)

    这篇文章主要介绍了关于数据与后端进行交流匹配(点亮星星) 的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-08-08

最新评论