最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript淺層克隆與深度克隆示例詳解

 更新時(shí)間:2020年09月01日 11:19:27   作者:小晗同學(xué)  
這篇文章主要給大家介紹了關(guān)于JavaScript淺層克隆與深度克隆的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

1 相關(guān)知識(shí)點(diǎn)

  1. 淺克隆就是將棧內(nèi)存中的引用復(fù)制一份,賦給一個(gè)新的變量,本質(zhì)上兩個(gè)指向堆內(nèi)存中的同一地址,內(nèi)容也相同,其中一個(gè)變化另一個(gè)內(nèi)容也會(huì)變化。
  2. 深克隆就是創(chuàng)建一個(gè)新的空對(duì)象,開辟一塊內(nèi)存,然后將原對(duì)象中的數(shù)據(jù)全部復(fù)制過去,完全切斷兩個(gè)對(duì)象間的聯(lián)系。
  3. 區(qū)別:淺克隆和深克隆最大的區(qū)別就是對(duì)引用值的處理了,即淺克隆之后你改我也改,深克隆之后你改我不改。(PS:原始值的處理一樣)
  4. 原始值(棧數(shù)據(jù)stack):Number,Boolean(false/true),String,undefined,null
  5. 引用值(堆數(shù)據(jù)heap):Array,Object,function ··· Date,RegExp

2 淺層克隆

在淺層克隆中,原始值的克隆沒問題,只是值的拷貝,不會(huì)出現(xiàn)你改我改的問題。但是引用值的克隆,就會(huì)出現(xiàn)你改我也改的問題,因?yàn)闇\層克隆的是地址,即指向的是同一空間。

2.1 淺克隆函數(shù)

function clone(origin, target) {
  var target = target || {}; 
  //容錯(cuò),即防止用戶不傳遞目標(biāo)參數(shù)。若用戶傳遞了參數(shù)就用,若沒傳則拿一個(gè)空對(duì)象當(dāng)目標(biāo)
  for (var prop in origin) {
    target[prop] = origin[prop];
  }
  return target;
}

2.2 運(yùn)用實(shí)例

function clone(origin, target) {
  var target = target || {}; 
  for (var prop in origin) {
    target[prop] = origin[prop];
  }
  return target;
}

var obj = {
  name: 'abc',
  age: '18',
  sex: 'male',
  card: ['a', 'b', 'c'],
  book: {
    name: 'ccc',
    sbook: {
      name: 'aaa'
    }
  }
};
var newobj = {};

clone(obj, newobj);

運(yùn)行代碼如下:

3 深度克隆

進(jìn)行深度克隆之后,對(duì)于引用值的克隆的問題就會(huì)和原始值一樣我改你不改,因?yàn)樵谏疃瓤寺≈须m然是相同的東西,但是指向不同的空間。即深度克隆之后,值各自獨(dú)立,互不影響。

3.1 深克隆步驟分析

需要進(jìn)行深度克隆的對(duì)象如下:

var obj = {
  name: 'abc', // 原始值
  age: '18', // 原始值
  sex: 'male',// 原始值
  card: ['a', 'b', 'c'], // 引用值
  book: { // 引用值
    name: 'ccc', // 原始值
    sbook: { // 引用值
      name: 'aaa'// 原始值
    }
  }
};

var obj1 = {};

(1)首先需要遍歷要克隆的對(duì)象

方法:for (var prop in origin){···}

for (var prop in origin) {
	···
}

(2)依次判斷是不是原始值

方法:typeof() ,即若為原始值,就直接拷貝;若為引用值(typeof(···)返回的值是object),則進(jìn)行遞歸操作。需要注意是的typeof(null) == 'object',所以得排除這一個(gè)情況。

if (origin[prop] !== "null" && typeof(origin[prop]) == 'object') {
	···
	// 遞歸
} else {
  target[prop] = origin[prop];
}

(3)判斷是數(shù)組還是對(duì)象

方法:toString(推薦), constructor,instanceof (后兩個(gè)會(huì)涉及到父子域的小問題,雖然遇到的可能不是很大)

var toStr = Object.prototype.toString,
  arrStr = "[object Array]";
if (toStr.call(origin[prop]) == arrStr) {
	··· // 數(shù)組
} else {
	··· // 對(duì)象
}

(4)建立相應(yīng)的數(shù)組或?qū)ο?/strong>

方法:建立一個(gè)新的同名空數(shù)組 / 對(duì)象,并將原始對(duì)象中的 數(shù)組或?qū)ο?當(dāng)成一個(gè)新的原始對(duì)象,再次將其中的數(shù)據(jù)拷貝到目標(biāo)對(duì)象的 同名空數(shù)組 / 對(duì)象 里面。即遞歸開始拷貝數(shù)組或?qū)ο罄锩娴臄?shù)據(jù),并遞歸執(zhí)行第(1)步。遞歸完成之后,再依次進(jìn)行下一個(gè)數(shù)據(jù)的克隆。

var toStr = Object.prototype.toString,
  arrStr = "[object Array]";
if (toStr.call(origin[prop]) == arrStr) {
	target[prop] = [];
} else {
	target[prop] = {};
}
newobj = {
  name: 'abc',
  age: '18',
  sex: 'male',
  card: [] 
  // 建立一個(gè)新的同名空數(shù)組,并把obj的card數(shù)據(jù)當(dāng)成一個(gè)原始對(duì)象,再次拷貝到obj1的card里面
  // 即 遞歸開始拷貝數(shù)組或?qū)ο罄锩娴臄?shù)據(jù),遞歸執(zhí)行第(1)步
  // 執(zhí)行完數(shù)組card拷貝之后,開始同理拷貝下一個(gè)對(duì)象book···
}

3.2 深克隆函數(shù)

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] = {};
        }
        deepClone(origin[prop], target[prop]);

      } else {
        target[prop] = origin[prop];
      }
    }
  }
  return target;
}

使用三目運(yùn)算符簡(jiǎn)化后的代碼如下:

// 使用三目運(yùn)算符簡(jiǎn)化后
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') {
        target[prop] = toStr.call(origin[prop]) == arrStr ? [] : {};
        deepClone(origin[prop], target[prop]);
      } else {
        target[prop] = origin[prop];
      }
    }
  }
  return target;
}

3.3 運(yùn)用實(shí)例

// 使用三目運(yùn)算符簡(jiǎn)化后
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') {
        target[prop] = toStr.call(origin[prop]) == arrStr ? [] : {};
        deepClone(origin[prop], target[prop]);
      } else {
        target[prop] = origin[prop];
      }
    }
  }
  return target;
}

運(yùn)行代碼如下:

3.4 hasOwnProperty

hasOwnProperty() 方法會(huì)返回一個(gè)布爾值,指示對(duì)象自身屬性中是否具有指定的屬性(即是否有指定的鍵)。

語法:obj.hasOwnProperty(prop)
參數(shù):要檢測(cè)的屬性的字符串形式表示的名稱,或者Symbol。
返回值:用來判斷某個(gè)對(duì)象是否含有指定的屬性的布爾值。
描述:所有繼承了Object的對(duì)象都會(huì)繼承到hasOwnProperty方法。這個(gè)方法可以用來檢測(cè)一個(gè)對(duì)象是否含有特定的自身屬性;和in運(yùn)算符不同,該方法會(huì)忽略掉那些從原型鏈上繼承到的屬性。
用法:
a. 使用hasOwnProperty方法判斷屬性是否存在
b. 區(qū)別自身屬性與繼承屬性
c. 遍歷一個(gè)對(duì)象的所有自身屬性
d. 使用hasOwnProperty作為屬性名
具體知識(shí)點(diǎn)請(qǐng)參考 Object.prototype.hasOwnProperty()

若對(duì)象里面編寫了原型屬性,但遍歷的時(shí)候并不想讓其顯示出來,就可以使用對(duì)象名.hasOwnProperty(屬性名) 來判斷是否是自身屬性,若是自己的則返回值為true,若不是自身原型屬性則返回值為false。實(shí)例如下:

var obj = {
	name: 'ABC',
	age: '18',
	sex: 'male',
	__proto__: {
		heart: 'happy'
	}
}
for (var prop in obj) {
	// 配套使用,起到一個(gè)過濾的作用,不把原型鏈上的數(shù)據(jù)弄出來
	if (obj.hasOwnProperty(prop)) {
		console.log(obj[prop]);// ABC 18 male
	}
}

個(gè)人筆記,歡迎大家交流探討!

總結(jié)

到此這篇關(guān)于JavaScript淺層克隆與深度克隆的文章就介紹到這了,更多相關(guān)JavaScript淺層克隆與深度克隆內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

尚志市| 临城县| 宝山区| 惠东县| 报价| 宜昌市| 精河县| 宁都县| 永福县| 眉山市| 资兴市| 竹溪县| 兰西县| 邹城市| 云霄县| 浮山县| 萝北县| 电白县| 娄烦县| 恩平市| 西贡区| 桐乡市| 水城县| 上虞市| 灵石县| 偃师市| 合山市| 沿河| 通化市| 阳春市| 大化| 库伦旗| 汪清县| 镇巴县| 商洛市| 隆林| 义马市| 吉首市| 大田县| 监利县| 子长县|