精华内容
下载资源
问答
  • 原生JS实现深拷贝

    千次阅读 2018-06-30 09:20:47
    所以对于基本数据类型来说他的任何赋值都深拷贝,因为在栈内存中,数据的大小是固定,不可变的,变量一旦声明就会在内存中在栈内存中开辟一个新的空间。我们常说的深拷贝是针对于引用类型的。引用类型在栈内存中只...

        说到深浅拷贝的问题,其实就是基本类型和引用类型数据拷贝的问题,再深一点就是栈内存和堆内存的区别。

    栈内存

        保存基本数据类型或者引用类型数据的地址指针。

    堆内存

        保存对象本身。

        所谓的深拷贝就是在内存中单独为该变量开辟一个存储空间。所以对于基本数据类型来说他的任何赋值都深拷贝,因为在栈内存中,数据的大小是固定,不可变的,变量一旦声明就会在内存中在栈内存中开辟一个新的空间。常说的深拷贝是针对于引用类型的。引用类型在栈内存中只保存了一个指向堆内存的指针,所以一般我们在将一个引用类型赋值给另外一个变量的时候,实际上是将这个引用类型在栈内存中指针赋值给了这变量,而最终这个变量指向的堆内存中的同一个对象。
    这里写图片描述
    举例:

    var obj1 = {name:"wangyy"};
    var obj2 = obj1;
    obj2.name="wangjunjie";
    console.log("obj1:",obj1);
    console.log("obj2:",obj2);
    运行结果:obj1:{name:"wangjunjie"}
             obj2:{name:"wangjunjie"}

        发现在改obj2的时候obj1也跟着改变了,这就是他们指针指向的是同一个内存对象,所以改也是改的同一个对象。但这不是我们希望的赋值 ,我们希望在赋值结束后彼此之前再无瓜葛,那我们应该怎样实现呢?
    好了不多说了,上代码了。

    方法一:

    Object.assign();

    var target = {};
    var source = {name:"wangyy"}
    Object.assign(target,source);
    target.name="wangjunjie";
    console.log("target:",target);
    console.log("source:",source);
    
    运行结果:target:{name:"wangjunjie"}
             source:{name:"wangyy"}

        貌似可以实现深拷贝,在这种情况下也确实能达到我们的目的,但是这种方式是有缺陷的,当对象的属性值也是一个对象的时候,它几现原形了。

    var target = {};
    var source = {name:"wangyy",family:{mother:"wuxl","father":"wangxy"}}
    Object.assign(target,source);
    target.family.sister="wanghm";
    console.log("target:",target);
    console.log("source:",source);

        通过运行结果可以发现Object.assign只能对于像上面那种简单对象可以实现深拷贝,对于复杂对象就无能为力了。

    方法二:

    将对象转成字符串:

    var target = {};
    var source = {name:"wangyy",family:{mother:"wuxl","father":"wangxy"}}
    target = JSON.parse(JSON.stringify(source ))
    target.family.sister="wanghm";
    console.log("target:",target);
    console.log("source:",source);

        哎!好像可以实现呢,而且也是想对比较号实现的。但是如果出爱心下面这种情况就凉凉了

    var target = {};
    var source = {
             name:"wangyy",
             family:{
                      mother:"wuxl",
                      father:"wangxy",
                    }
             }
    target = JSON.parse(JSON.stringify(source ))
    target.family.sister="wanghm";
    console.log("target:",target);
    console.log("source:",source);

        运行后我们发现source中的func属性不见了。所以这种方式还是有局限性的,必须是标准格式的JSON数据。

    方法三:

        看来向上面这种一步到位实现深拷贝是不显示了,那下面就专门写一个深拷贝的方法来实现:

    function deepClone(data){
        if(!data|!(datainstanceof Object)|(typeof data=="function")){
             return data||undefined;
        }
        var constructor = data.constructor;
        var result = new constructor();
        for(var key in data){
            if(data.hasOwnProperty(key)){
               result[key]=deepClone(data[key]);
            }
        }
        return result;
    }

    本质就是区分基本数据类型和引用数据类型,然后进行递归操作,over!

    展开全文
  • 借鉴了一位大佬的想法:...1、首先实现一个函数对变量类型进行判断 // 判断变量的类型 function getType(obj){ var str = Object.prototype.toString.call(obj); // typeof 不能准确判断一个对象变量, ...

    借鉴了一位大佬的想法:https://blog.csdn.net/LL18781132750/article/details/79700089

    1、首先实现一个函数对变量类型进行判断
    // 判断变量的类型
    function getType(obj){
    	var str = Object.prototype.toString.call(obj);  // typeof 不能准确判断一个对象变量,
    	//null 的结果也是 object,数组的结果也是 object
    	
    	var map={
    		'[object Boolean]'  : 'boolean', 
    		'[object Number]'   : 'number', 
    		'[object String]'   : 'string', 
    		'[object Function]' : 'function', 
    		'[object Array]'    : 'array', 
    		'[object Date]'     : 'date', 
    		'[object RegExp]'   : 'regExp', 
    		'[object Undefined]': 'undefined',
    		'[object Null]'     : 'null', 
    		'[object Object]'   : 'object'
    	}
    	//if(obj instanceof Element){ //判断是否是dom元素,如div等
    		//return "element";
    	//}
    	return map[str];
    }
    

    2、下面我们实现deepCopy函数,对对象中的数组或对象进行递归调用拆分复制

    //深拷贝函数
    function deepCopy(p){
    	var obj;
    	var str = getType(p);
    	if(str == 'array'){
    		obj = [];
    		for (var i = 0; i < p.length; i++) {
    			obj.push(arguments.callee(p[i]));  //argument为函数内部对象,包含传入函数的所有参数,
    			//arguments.callee代表函数名,多用于递归调用,防止函数执行与函数名紧紧耦合的现象,
    			//对于没有函数名的匿名函数也非常起作用。
    		}
    	}else if(str == 'object'){
    		obj = {};
    		for(var i in p){
    			obj[i] = arguments.callee(p[i]);
    		}
    	}else{
    		return p;
    	}
    	return obj;
    }
    
    

    3、测试案例

    var a={
    	color:['red','blue','black'],
    	age:10,
    }
    var b = deepCopy(a);
    b.color.push('green');
    console.log(a);
    console.log(b);
    
    
    特殊方法:JSON.parse(JSON.stringify(object))
    局限性:
    a.会忽略 undefined
    b.不能序列化函数,会被忽略
    c.不能解决循环引用的对象
    展开全文
  • 利用原生JS实现深拷贝 原生JS的数据类型包括值类型和引用类型: 对于值类型(undefined;string;number;boolean;symbol;),可以很方便的使用赋值操作, 但对于引用类型(Array,Object),简单的进行赋值操作,...

    浅拷贝与深拷贝概述:

    1.浅拷贝只是拷贝一层,更深层次对象级别只拷贝引用;
    2.深拷贝拷贝多层,每一级别的数据都会拷贝;

    利用原生JS实现深拷贝

    原生JS的数据类型包括值类型引用类型
    对于值类型(undefined;string;number;boolean;symbol;),可以很方便的使用赋值操作,
    但对于引用类型(Array,Object),简单的进行赋值操作,赋值得到的只是地址,俗称浅拷贝,如下:

    const obj = {
        a: 13,
        b: { name: 'zhangsan', age: 13 },
        c: [1, 3, 4]
    };
    const obj2 = obj;
    obj2.c[0] = 23;
    console.log(obj.c[0]); //23
    

    对obj2中的值修改也会更改obj中的值,因此就需要进行深拷贝操作,避免这种简单赋值操作带来的影响,代码如下:

    const obj = {
        a: 13,
        b: { name: 'zhangsan', age: 13 },
        c: [1, 3, 4]
    };
    function deepClone(obj = {}) {
        //判断值类型
        if (typeof obj !== 'object' || typeof obj == null) {
            return obj
        };
        //初始化result值
        let result;
        if (obj instanceof Array) {
            result = [];
        } else {
            result = {};
        };
        //进行赋值操作
        for (let key in obj) {
            //判断key是不是obj本身所含的属性,保证key不是原型属性
            if (obj.hasOwnProperty(key)) {
            	//递归
                result[key] = deepClone(obj[key]);
            }
        };
        return result;
    }
    const obj3 = deepClone(obj);
    obj3.c[0] = 23;
    console.log(obj.c[0]);//1
    

    综上,实现深拷贝有几个注意点:

    1.判断值类型和应用类型
    2.判断是数组还是对象
    3.递归
    
    展开全文
  • 原生js实现深拷贝

    2020-07-13 17:47:13
    function deepClone (obj) { let result = Array.isArray(obj) ? [] : {} for (let key in obj) { if (obj.hasOwnProperty(key)) { if (typeof obj[key] === “object”) { result[key] = deepClone(obj[key]) ...

    function deepClone (obj) {
    let result = Array.isArray(obj) ? [] : {}
    for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
    if (typeof obj[key] === “object”) {
    result[key] = deepClone(obj[key])
    } else {
    result[key] = obj[key]
    }
    }
    }
    return result
    }

    展开全文
  • 原生JS实现深拷贝

    2020-12-23 15:15:24
    原生JS实现深拷贝 浅拷贝和深拷贝的概念这里不做赘述。 思路: 当拷贝的元素不是基础类型时,他只会进行浅拷贝。 赋值的时候(如var a =b),若其是基础类型(b是基础类型(ex:Boolean、String、Number)),则会...
  • //深拷贝---------->>>>>>>> //遍历 //判断是否为原始值,是原始值直接浅拷贝 //判断是否为引用值(数组或对象),是的话直接创建新的数组或者对象 //递归,重复上述步骤 创建新对象person1...
  • 为什么需要深拷贝 因为对象直接复制给另外一个变量时,2个变量的值指向堆栈中同一条数据,改变其中一个变量中某个key的value,都会影响到另外一个变量的值 数据类型 很多博客直接就typeof判断数据类型了...
  • 至于不懂什么是浅拷贝和深拷贝的出门右转百度,这里只做js源码的分享,以下奉上代码 浅拷贝: var a={username:'张三'}; var b = copy(a) function copy(a) { let b = {} for (let attr in a) { b[attr] = a[attr]...
  • 原生js实现对象的深拷贝及循环引用

    千次阅读 2020-02-18 17:22:11
    我们使用Object.assign(target,…sources)时,其实只是浅拷贝。只能复制第一层属性,而如果第一层属性中有对象的话,其实只是对对象的引用而已。 我们修改target里的对象属性时,source对象中对应的对象属性也会改变...
  • // 可以用Object.getPrototypeOf(obj)代替obj.__proto__ const clone = (source, target={}) => { let names = Object.getOwnPropertyNames(source) for (let i = 0; i < names.length;...
  • js原生实现一个深拷贝
  • &lt;html&gt; &lt;head&gt; &lt;title&gt;&lt;/title&gt;...text/javascript"&gt; function copy(arr){ var obj=arr.constructor==Array?[]:{};  //
  • JS实现深拷贝

    千次阅读 2019-06-01 00:53:17
    朋友去面试遇到的面试题~我也不会顺路来学习一下 本篇文章参考了[link]...什么是深拷贝? 想要搞清楚什么是深拷贝,就需要先搞清楚一个数据的存储是在堆内存还是栈内存。 在JS中,基本数据类型有number...
  • 原生js深拷贝函数

    2019-07-02 19:13:00
    function deepClone(data){  if(!data || !(data instanceof Object) || (typeof data=="function"))  {  return data||undefined; ... var constructor = data.constructor;... var result = new const...
  • 实现深拷贝的方式 JSON方法实现 //_tmp和result是相互独立的,没有任何联系,有各自的存储空间。 let deepClone = function (obj) { let _tmp = JSON.stringify(obj);//将对象转换为json字符串形式 let result =...
  • js实现深拷贝的4种方法

    千次阅读 2020-12-11 15:21:00
    原生js中递归函数拷贝 将数据中所有的数据拷贝下来,对拷贝之后的数据进行修改不会影响到原数据 ,两个对象或数组不共享一块内存 <script> let obj={ abc:'123', def:[{a:1,b:2,c:3},{q:8,w:9}], qwe:{e...
  • 目录实现代码 实现 代码 function deepClone(oldArray, newArray) { var obj = newArray || {}; for (var i in a) { if (typeof a[i] === 'object') { obj[i] = (a[i].constructor === Array) ? [] : {}; ...
  • 原生实现深拷贝的接口 需要深拷贝的原因 在js当中非基本数据类型(引用类型),在相互之间进行赋值的时候其实赋值的是指针,所以如果A引用类型赋值给B,是将A的指针赋给了B,所以在改变B里面内容的时候,A的内容会...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 7,044
精华内容 2,817
关键字:

原生js实现深拷贝