在学习的过程中写这篇文章,总结一些学习克隆要点
在进行克隆的环节前要了解什么是原始值和引用值 在 ECMAScript 中,变量可以存在两种类型的值,即原始值和引用值。以下是W3C的定义 1.原始值:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。 有五个值:Undefined,Null,Boolean,Number,String 2.引用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存处。 包括 Object(Array也是Object)、Function、Date、RegExp。
克隆的过程 1.遍历你所要克隆的对象/数组:for(var prop in obj) / for(var prop in arr) ps:数组是一个特殊的对象,因此for in 循环通吃数组和对象
2.判断是不是原始值 typeof() ,返回是object基本是引用值,除了null,其他是原始值
3.判断是数组还是对象 识别一个变量里面传的的数组还是对象有三种方法 (1).constructor (2).instanceof (3).toString()方法
4.重新建立一个空的,相应的数组或对象
5.递归(递归核心思想:(1)找规律 (2)找出口)
因为原始值存储在栈中。意思就是说,当一个原始变量把值赋给另一个原始变量时,只是把栈中的内容复制给另一个原始变量,此时这两个变量互不影响,即当一个变量值改变时,另一个变量不会因此而发生任何变化。
简单来说:就是克隆了另外一个仓库,有两个仓库,互不影响,但这是克隆对象只有原始值的情况下
例子:
var obj = { name :'wzy', sex:'male', age:24 } var obj1 = {}; function clone(origin,target){ var target = target || {}; for(var prop in origin){ target[prop] = origin[prop] } return target; } clone(obj,obj1);这个例子obj的值全部是原始值,因此直接遍历对象然后克隆
当克隆的对象包含引用值时,这时候改变克隆的值,被克隆的对象也会改变。
因为引用值于原始值不同,引用值把引用变量存储在栈中,而实际的对象存储在堆中。每一个引用变量都有一根指针指向其堆中的实际对象。当变量改变时,另一个变量也会改变.因此要用深度克隆
简单来说:引用值其实提供一个仓库的地址,你改变了这个仓库的东西,那么你克隆的对象会因为这个仓库改变而改变,因此深度克隆很有必要 例子:
var obj = { name :'wzy', sex:'male', age:24, card:[5,'zy'], dasd:{ a:888, d:'gg' } } var obj1 = {} function deepClone(origin,target){ var target = target || {}, toStr = Object.prototype.toString, arrStr = '[object Array]'; for(var prop in origin){ if(origin.hasOwnProperty(prop)){ if (origin[prop] !== 'null' &&typeof(origin[prop]) == 'object'){ // if(toStr.call(origin[prop])==arrStr){ // target[prop]=[]; // }else{ // target[prop]={}; // } // 用三目运算符可以简洁代码判断 target[prop]=(toStr.call(origin[prop])==arrStr)? [] :{}; deepClone(origin[prop],target[prop]); }else{ target[prop] = origin[prop]; } } } return target; }ps:(在后台验证时…)对象{}是不能直接.push方法的,要在对象里手动添加。数组[ ]倒是可以直接用.push方法
上面的例子中,obj有对象和数组,但是用了深度克隆就不会互相影响了
总结: 克隆前来要判断, 原始引用要区分。 克隆好来五步走, 一步不缺无BUG。
