首頁  >  文章  >  web前端  >  javascript對淺拷貝和深拷貝的詳解

javascript對淺拷貝和深拷貝的詳解

高洛峰
高洛峰原創
2017-01-03 15:52:461120瀏覽

下面小編就為大家帶來一篇淺談JavaScript中物件導向的深拷貝和淺拷貝。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。

1.淺拷貝:複製一份引用,所有引用對像都指向一份數據,並且都可以修改這份數據。

2.深拷貝(複雜):複製變數值,對於非基本類型的變量,則遞歸至基本類型變數後,再複製。

這裡畫一個簡單的圖來加深理解:

javascript對淺拷貝和深拷貝的詳解

一、數組的深淺拷貝

在使用JavaScript對數組經常操作的時候,我們備份需要將數組進行簡單設定,事實證明如果只是簡單的將它賦予其他變量,那麼我們只要更改其中的任何一個,然後其他的也會跟著改變,這就導致了問題的發生。

var arr = ["One","Two","Three"];
var arrto = arr;
arrto[1] = "test";
document.writeln("数组的原始值:" + arr + "
");//Export:数组的原始值:One,test,Three document.writeln("数组的新值:" + arrto + "
");//Export:数组的新值:One,test,Three

像上面的這種直接賦值的方式就是淺拷貝,很多時候,這樣並不是我們想要得到的結果,其實我們想要的是arr的值不變,不是嗎? 

方法一:js的slice函數 

var arr = ["One","Two","Three"];
var arrtoo = arr.slice(0);
arrtoo[1] = "set Map";
document.writeln("数组的原始值:" + arr + "
");//Export:数组的原始值:One,Two,Three document.writeln("数组的新值:" + arrtoo + "
");//Export:数组的新值:One,set Map,Three

方法二:js的concat方法

var arr = ["One","Two","Three"];
var arrtooo = arr.concat();
arrtooo[1] = "set Map To";
document.writeln("数组的原始值:" + arr + "
");//Export:数组的原始值:One,Two,Three document.writeln("数组的新值:" + arrtooo + "
");//Export:数组的新值:One,set Map To,Three

二、物件的深淺拷貝

var a={name:'yy',age:26};
var b=new Object();
b.name=a.name;
b.age=a.age;
a.name='xx';
console.log(b);//Object { name="yy", age=26}
console.log(a);//Object { name="xx", age=26}

就是把物件的屬性遍歷一遍,賦給一個新的物件。

var deepCopy= function(source) { 
var result={};
for (var key in source) {
 result[key] = typeof source[key]==='object'? deepCoyp(source[key]): source[key];
 } 
 return result; 
}

舉一個jQuery中的例子:

jQuery.extend = jQuery.fn.extend = function() {//1.将extend方法扩展到JQ(函数)下边:扩展静态方法
 //2. jQuery.fn.extend 把extend扩展到jq.fn下 且jQuery.fn = jQuery.prototype 扩展实例方法
 // 1.2.功能相似
 var options, name, src, copy, copyIsArray, clone, //定义一些变量
 target = arguments[0] || {}, 
 //目标元素是【0】第一个元素$.extend( a , { name : 'hello' } , { age : 30 } );
 i = 1, //第一个元素的位置
 length = arguments.length,//第一个个对象的元素
 deep = false; //是否是深拷贝 默认 false不是
 
 // Handle a deep copy situation 看是不是深拷贝情况
 if ( typeof target === "boolean" ) { //是布尔值 
 deep = target;
 target = arguments[1] || {}; //目标元素是第二个$.extend( true , a , b )
 // skip the boolean and the target
 i = 2;
 }
 
 // Handle case when target is a string or something (possible in deep copy) 看参数正确不
 if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
 // 当目标不是对象或者不是函数的时候
 target = {}; //变成一个空的jason
 }
 
 // extend jQuery itself if only one argument is passed看是不是插件情况
 if ( length === i ) { //只写了一个对象 要把这个对象扩展到jq源码上 静态方法 或者是实例方法
 target = this; //this 是$ 或者 $();
 --i;
 }
// 可能有多个对象情况
 for ( ; i < length; i++ ) {
 // Only deal with non-null/undefined values
 if ( (options = arguments[ i ]) != null ) {//看后边的对象是否都有值
 // Extend the base object
 for ( name in options ) {
 src = target[ name ];
 copy = options[ name ];
 
 // Prevent never-ending loop
 if ( target === copy ) {//防止循环引用 
  continue;//跳出本次循环继续执行
  // $.extend( a , { name : a } ) );循环引用 a也是一个对象
 }
 
 // Recurse if we're merging plain objects or arrays深拷贝
 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
  // 是深拷贝 且需有var b = { name : { age : 30 } }; 且b必须是对象自变量(jason) 或者是个数组
   
  //递归
  if ( copyIsArray ) { //数组
  copyIsArray = false;
  clone = src && jQuery.isArray(src) ? src : []; //定义一个空数组
 
  } else {//jason
  clone = src && jQuery.isPlainObject(src) ? src : {};//看原有的属性有没有且是不是jason定义一个空jason
  }
  // var a = { name : { job : 'it' } }; 看有没有原有的属性 有的话在原有的上边添加
  // var b = { name : {age : 30} };
  // $.extend( true , a , b );//a继承b
  // console.log( a ); a{ name:{ job : 'it' ,age : 30}} 如果只有一个{} 则只有,age : 30
  // Never move original objects, clone(a) them
  target[ name ] = jQuery.extend( deep, clone, copy ); 
  //调用函数本身进行进一步的递归处理 
 
 // Don't bring in undefined values浅拷贝
 } else if ( copy !== undefined ) {
  target[ name ] = copy; //直接复制因为里边没有对象
 }
 }
 }
 }
 
 // Return the modified object
 return target;
};

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持PHP中文網。

更多javascript對淺拷貝和深拷貝的詳解相關文章請關注PHP中文網!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn