精华内容
下载资源
问答
  • 原生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实现深拷贝

    千次阅读 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!

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

    2020-12-23 15:15:24
    原生JS实现深拷贝 浅拷贝和深拷贝的概念这里不做赘述。 思路: 当拷贝的元素不是基础类型时,他只会进行浅拷贝。 赋值的时候(如var a =b),若其是基础类型(b是基础类型(ex:Boolean、String、Number)),则会...

    用原生JS实现深拷贝

    浅拷贝和深拷贝的概念这里不做赘述。


    深拷贝实现方法有两种
    一种是通过JSON.parse(JSON.Stringify(arr));
    另一种则是通过递归,本文主要讲述通过递归实现JS的深拷贝。
    弊端:都不能实现对于内部函数的拷贝。


    通过JSON.parse(JSON.Stringify(arr))实现

    var arr = [1,4,{name:'yzk',age:20}];
    
    //实现深拷贝
    var arr2 = JSON.parse(JSON.stringify(arr));
    
    arr2[2].name='zd';
    console.log(arr1,arr2)
    

    通过递归实现

    思路:

    当拷贝的元素不是基础类型时,他只会进行浅拷贝。 赋值的时候(如var a =b),若其是基础类型(b是基础类型(ex:Boolean、String、Number)),则会重新用这个基础类型的值对其进行初始化(不会对其源头有影响)。

    //原理理解
    var a = 12;
        var b = a;
        console.log(a,b);//12,12
    
        b=6;
        console.log(a,b);//12,6
    

    深拷贝代码实现

    <script>
        function checkedType(target){
        	//实现对于每个参数的类型判定,若对这段代码不清楚,
        	//则把checkedType中的注释去掉看看执行结果即可理解。
        	// var arr = []
        	// var obj ={}
        	// var x = null
        	// console.log(Object.prototype.toString.call(arr)); //[object Array]
        	// console.log(Object.prototype.toString.call(obj)); //[object Object]
        	// console.log(Object.prototype.toString.call(null)); //[object Null]
            return Object.prototype.toString.call(target).slice(8,-1)
        }
    	
    	//实现深度克隆
        function clone(target) {
            // 判断拷贝的数据类型
            // 初始化变量result 成为最终克隆的类型
            let result, targetType = checkedType(target);
            if (targetType === 'Object') {
                result = {};
            } else if (targetType === 'Array') {
                result = [];
            } else {
                return target;
            }
    
            // 遍历目标数据
            for(let i in target){
                // 获取遍历数据结构的每一项
                //通过target[i]的方法:无论对象的属性还是数组的属性都能访问
                let value = target[i];
                if(checkedType(value)==='Object'||checkedType(value)==='Array'){
                    // 继续遍历获取到的value值
                    result[i] = clone(value);
                }else {
                    result[i] = value;
                }
            }
            return result;
        }
    
        var arr1 = [1,3,5,{name:'yzk',age:20}];
        var arr2 = clone(arr1);
        console.log(arr1,arr2);
        console.log('---------');
        arr2[3].name = 'zd';
        console.log(arr1,arr2);
    </script>
    

    输出结果
    当改变arr2中的arr2[3]对象的数据时,原来的arr1中的arr[3]并没有被影响,从而实现了深拷贝。
    在这里插入图片描述

    展开全文
  • 借鉴了一位大佬的想法:...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.不能解决循环引用的对象
    展开全文
  • 为什么需要深拷贝 因为对象直接复制给另外一个变量时,2个变量的值指向堆栈中同一条数据,改变其中一个变量中某个key的value,都会影响到另外一个变量的值 数据类型 很多博客直接就typeof判断数据类型了...
  • 利用原生JS实现深拷贝 原生JS的数据类型包括值类型和引用类型: 对于值类型(undefined;string;number;boolean;symbol;),可以很方便的使用赋值操作, 但对于引用类型(Array,Object),简单的进行赋值操作,...
  • js原生深拷贝

    2019-09-26 21:42:54
    /*****************************************************************************************/ ...原生js实现深拷贝 function clone(target){ if(typeof target === 'object'){ let obj = Array....
  • 上面代码中有测试输出原对象和深拷贝到newobj上的新对象,如果深拷贝成功的话,obj里面的引用类型改变值,是不会影响到新对象的。以下是在控制台打印的结果: 果然obj和newobj的引用类型互相没有影响,而不像...
  • // 可以用Object.getPrototypeOf(obj)代替obj.__proto__ const clone = (source, target={}) => { let names = Object.getOwnPropertyNames(source) for (let i = 0; i < names.length;...
  • var arr = [1,2,3,4,5,6]; function deepCopy(arr){ var obj = arr instanceof Array ? [] : {}//创建空数组或json来装... //for in arr 每个值拷贝到objzhong for(var item in arr){ if(typeof arr[item] ===...
  • 深拷贝原生js实现

    2018-03-14 18:02:00
    面试时被问到怎么实现深拷贝,想都没想就用var obj2=JSON.parse(JSON.stringify(obj1))来实现。但面试官却要我用循环写出来,那就只能用递归了。可惜当时一下子忘了判断是否为对象的方法,说出了原理还是被好衣买的...
  • function deepCopy(obj){ if(typeof obj !=='object'){ return obj }else{ let DCObj = obj instanceof Array ? [] : {}; for ( let item in obj){ ...
  • JSON序列化反序列化 var a = { b: 1, c: [1,2,3], d: {d1: 'ddd1', d2: 'dddd2'} } var a2 = JSON.parse(JSON.stringify(a)) // 验证一下:如果改这边,那边的值不变,那就说明是深拷贝 a2.b = 2 console.log(a.b) /...
  • 以前对深拷贝和浅拷贝没有太深的印象,后来才知道是因为没掉进去过它的坑里。最近掉坑了才意识到它们的重要性。 闲话少叙,来说说坑:如果我需要保存一个复杂的对象 obj 并把它赋值给 originalObj ,后来对obj对象的...

空空如也

空空如也

1 2 3 4 5
收藏数 86
精华内容 34
关键字:

原生js实现深拷贝