zoukankan      html  css  js  c++  java
  • JavaScript的深克隆与浅克隆

    JS数据类型分为两类: 基本类型(Number、Boolean、Undefined、Null、String、Symbol(ES6新加,此处不讨论))与引用类型(Object)。原始类型存储的是对象的实际数据,而对象类型存储的是对象的引用地址。

    两种克隆

    1. 浅克隆: 原始类型为值传递,对象类型仍为引用传递。

    2. 深克隆: 所有元素或属性均完全复制,与原对象完全脱离,也就是说所有对于新对象的修改都不会反映到原对象中。

    浅克隆

    1.对于基本类型:

    //数值克隆
    var a="1";
    var b=a;
    b="2";
    console.log(a);// "1"
    console.log(b);// "2"
    

    2.对于引用类型:

    我们都知道,函数在js中属于“一等公民”,同时也是引用类型,但是函数的克隆是通过浅克隆就可以实现,因为函数的克隆会在内存单独开辟一块空间,互不影响

    var m=function(){alert(1);};
    var n=m;
    n=function(){alert(2);};
     
    console.log(m());//1
    console.log(n());//2
    

    下面通过一段代码来看浅克隆的问题:

    function clone(obj){
        var result={};
        for(key in obj){
            result[key]=obj[key];
        }
        return result;
    }
    
    var dog = {
    	name: '大黄',
    	age: 8,
    	hobby: {
    		food: 'cookie',
    		toy: 'ball'
    	}
    }
    
    var oNew = clone(dog);
    console.log(dog.hobby.food);      // cookie
    oNew.hobby.food = "icecream";
    console.log(dog.hobby.food)       // icecream
    

    简单的复制对象,如果对象其中一个属性是引用型变量,就会出现这种情况,因为引用型变量保存的是内存地址,所以其实后来操作的都是同一块内存。

    深克隆

    1.JSON对象的parse和stringify

    JSON对象是ES5中引入的新的类型(支持的浏览器为IE8+),JSON对象parse方法可以将JSON字符串反序列化成JS对象,stringify方法可以将JS对象序列化成JSON字符串,借助这两个方法,也可以实现对象的深复制。

    var dog = {
    	name: '大黄',
    	age: 8,
    	hobby: {
    		food: 'cookie',
    		toy: 'ball'
    	}
    }
    
    var oNew = JSON.parse(JSON.stringify(dog));
    console.log(dog.hobby.food);      // cookie
    oNew.hobby.food = "icecream";
    console.log(dog.hobby.food)       // cookie
    

    该方法的局限性:

    1. 无法复制函数

    2. 原型链没了,对象就是object,所属的类没了。

    2.在jquery中extend方法可以用来扩展对象,这个方法可以传入一个参数:deep(true or false),表示是否执行深复制(如果是深复制则会执行递归复制),此处不细说。

    3.自己定义

    function deepClone(obj){
        var result,
    		oClass=isClass(obj);
    
        if(oClass==="Object"){
            result={};
        }else if(oClass==="Array"){
            result=[];
        }else{
            return obj;
        }
        for(key in obj){
            var copy=obj[key];
            if(isClass(copy)=="Object"){
                result[key]=arguments.callee(copy);//递归调用
            }else if(isClass(copy)=="Array"){
                result[key]=arguments.callee(copy);
            }else{
                result[key]=obj[key];
            }
        }
        return result;
    }
    //返回传递给他的任意对象的类
    function isClass(o){
        if(o===null) return "Null";
        if(o===undefined) return "Undefined";
        return Object.prototype.toString.call(o).slice(8,-1);
    }
    

    或者可以写为(只适用引用类型):

    Object.prototype.clone = function(){
    
        var o = this.constructor === Array ? [] : {};
    
        for(var e in this){
                o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];
        }
        return o;
    }
  • 相关阅读:
    Git的安装
    报错Invalid character found in method name. HTTP method names must be tokens|the HTTP protoco
    Spring Cloud(二)—— Eureka注册与发现
    spring-boot swagger2 设置全局token,说明页面接口无法带入token
    c# 结构体中包含结构体数组的使用
    百度地图api热力图时报错Cannot read property 'y' of undefined
    springboot使用freemaker导出word文档
    c# 同时运行两个相同的程序
    idea maven的pom文件已导入依赖,但是无法引入该包中class
    bootstrap Table 导出时时间格式显示秒 科学计数法显示
  • 原文地址:https://www.cnblogs.com/ylweb/p/7762641.html
Copyright © 2011-2022 走看看