国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Javascript 中的對(duì)象拷貝

lieeps / 1160人閱讀

摘要:原文在這篇文章中我們將會(huì)討論中對(duì)象拷貝的多種方式。因此,根據(jù)你的用法需要特別注意的對(duì)象拷貝。在擁有權(quán)限的情況下,通知立即關(guān)閉。在中深拷貝不幸的是,結(jié)構(gòu)化拷貝算法目前僅適用于基于瀏覽器的應(yīng)用。

原文:COPYING OBJECTS IN JAVASCRIPT
在這篇文章中我們將會(huì)討論 Javascript 中對(duì)象拷貝的多種方式。包括深拷貝和淺拷貝。
開(kāi)始之前,先談一些基礎(chǔ)知識(shí): Javascript 中的對(duì)象只是對(duì)內(nèi)存中某個(gè)地址的引用。這些引用是可變的,即它們可以重新分配。因此,簡(jiǎn)單制作一個(gè)引用的副本只會(huì)導(dǎo)致2個(gè)引用指向內(nèi)存中相同的地址:

var foo = {
    a : "abc"
}
console.log(foo.a); // abc

var bar = foo;
console.log(bar.a); // abc

foo.a = "yo foo";
console.log(foo.a); // yo foo
console.log(bar.a); // yo foo

bar.a = "whatup bar?";
console.log(foo.a); // whatup bar?
console.log(bar.a); // whatup bar?  

在上面的例子中可以看到,不管是foo還是bar都反映了它們對(duì)象上的變化。因此,根據(jù)你的用法需要特別注意Javascript的對(duì)象拷貝。

淺拷貝

如果你的對(duì)象只有值類型的屬性,則可以用拓展語(yǔ)法或者

Object.assign(...)
var obj = { foo: "foo", bar: "bar" };

var copy = { ...obj }; // Object { foo: "foo", bar: "bar" }
var obj = { foo: "foo", bar: "bar" };

var copy = Object.assign({}, obj); // Object { foo: "foo", bar: "bar" }

注意,上述兩種方法都可以將屬性值從多個(gè)源對(duì)象復(fù)制到目標(biāo)對(duì)象:

var obj1 = { foo: "foo" };
var obj2 = { bar: "bar" };

var copySpread = { ...obj1, ...obj2 }; // Object { foo: "foo", bar: "bar" }
var copyAssign = Object.assign({}, obj1, obj2); // Object { foo: "foo", bar: "bar" }

上述方法的問(wèn)題在于對(duì)于對(duì)象的屬性是對(duì)象的對(duì)象,只復(fù)制了引用地址,即它相當(dāng)于執(zhí)行 var bar = foo,與第一個(gè)代碼示例一樣:

var foo = { a: 0 , b: { c: 0 } };
var copy = { ...foo };

copy.a = 1;
copy.b.c = 2;

console.dir(foo); // { a: 0, b: { c: 2 } }
console.dir(copy); // { a: 1, b: { c: 2 } }
深拷貝(警告)

對(duì)于更加復(fù)雜的情況,可以使用較新的被稱為“結(jié)構(gòu)化拷貝”的HTML5拷貝算法。不幸的是,它仍局限于某些內(nèi)置類型,但它支持的類型比 JSON.parse 多得多:Date, RegExp, Map, Set, Blob, FileList, ImageData, 稀疏和類型化的Array。它還保留了拷貝數(shù)據(jù)中的引用,允許它支持不能與上述序列化方法一起使用的循環(huán)和遞歸結(jié)構(gòu)。
目前沒(méi)有直接的方法來(lái)調(diào)用結(jié)構(gòu)化拷貝算法,但是有一些較新的瀏覽器功能在引擎幫助下使用了這個(gè)算法。因此有幾個(gè)可以用來(lái)深拷貝的解決方法。
通過(guò) MessageChannels:它的想法是利用通信功能使用的序列化算法。由于這個(gè)功能是基于事件的,因此生成的拷貝也是異步操作。

class StructuredCloner {
  constructor() {
    this.pendingClones_ = new Map();
    this.nextKey_ = 0;

    const channel = new MessageChannel();
    this.inPort_ = channel.port1;
    this.outPort_ = channel.port2;

    this.outPort_.onmessage = ({data: {key, value}}) => {
      const resolve = this.pendingClones_.get(key);
      resolve(value);
      this.pendingClones_.delete(key);
    };
    this.outPort_.start();
  }

  cloneAsync(value) {
    return new Promise(resolve => {
      const key = this.nextKey_++;
      this.pendingClones_.set(key, resolve);
      this.inPort_.postMessage({key, value});
    });
  }
}

const structuredCloneAsync = window.structuredCloneAsync =
    StructuredCloner.prototype.cloneAsync.bind(new StructuredCloner);


const main = async () => {
  const original = { date: new Date(), number: Math.random() };
  original.self = original;

  const clone = await structuredCloneAsync(original);

  // different objects:
  console.assert(original !== clone);
  console.assert(original.date !== clone.date);

  // cyclical:
  console.assert(original.self === original);
  console.assert(clone.self === clone);

  // equivalent values:
  console.assert(original.number === clone.number);
  console.assert(Number(original.date) === Number(clone.date));

  console.log("Assertions complete.");
};

main();

通過(guò) history API: history.pushState()history.replaceState() 都創(chuàng)建了它們第一個(gè)參數(shù)的結(jié)構(gòu)化拷貝!注意當(dāng)這個(gè)方法是異步的時(shí)候,操縱瀏覽器歷史記錄不再是一個(gè)快速操作,反復(fù)調(diào)用此方法可能會(huì)導(dǎo)致瀏覽器無(wú)響應(yīng)。

const structuredClone = obj => {
  const oldState = history.state;
  history.replaceState(obj, null);
  const clonedObj = history.state;
  history.replaceState(oldState, null);
  return clonedObj;
};

通過(guò) notification API:在創(chuàng)建新通知時(shí),構(gòu)造函數(shù)會(huì)創(chuàng)建它關(guān)聯(lián)數(shù)據(jù)的結(jié)構(gòu)化拷貝。注意它還會(huì)嘗試向用戶顯示瀏覽器通知,但是除非應(yīng)用程序已經(jīng)請(qǐng)求到了顯示通知的權(quán)限,否則這個(gè)操作將會(huì)失敗。在擁有權(quán)限的情況下,通知立即關(guān)閉。

const structuredClone = obj => {
  const n = new Notification("", {data: obj, silent: true});
  n.onshow = n.close.bind(n);
  return n.data;
};
在 NODE.JS 中深拷貝

不幸的是,結(jié)構(gòu)化拷貝算法目前僅適用于基于瀏覽器的應(yīng)用。對(duì)于服務(wù)端,可以使用 lodashcloneDeep 方法,該方法也是基于結(jié)構(gòu)化拷貝方法。

結(jié)論

總而言之,在Javascript中拷貝對(duì)象的最佳算法很大程度上取決于你要復(fù)制的對(duì)象的內(nèi)容和類型。雖然 lodash 是最安全的通用深拷貝方法,但如果你自己動(dòng)手,可能會(huì)獲得更高效的實(shí)現(xiàn),以下是一個(gè)適用于日期的簡(jiǎn)單深拷貝的例子:

function deepClone(obj) {
  var copy;

  // Handle the 3 simple types, and null or undefined
  if (null == obj || "object" != typeof obj) return obj;

  // Handle Date
  if (obj instanceof Date) {
    copy = new Date();
    copy.setTime(obj.getTime());
    return copy;
  }

  // Handle Array
  if (obj instanceof Array) {
    copy = [];
    for (var i = 0, len = obj.length; i < len; i++) {
        copy[i] = deepClone(obj[i]);
    }
    return copy;
  }

  // Handle Function
  if (obj instanceof Function) {
    copy = function() {
      return obj.apply(this, arguments);
    }
    return copy;
  }

  // Handle Object
  if (obj instanceof Object) {
      copy = {};
      for (var attr in obj) {
          if (obj.hasOwnProperty(attr)) copy[attr] = deepClone(obj[attr]);
      }
      return copy;
  }

  throw new Error("Unable to copy obj as type isn"t supported " + obj.constructor.name);
}

就個(gè)人而言,我期待能夠在任何地方使用結(jié)構(gòu)化拷貝,最后把這個(gè)問(wèn)題放一邊,快樂(lè)的拷貝:)
注:若有問(wèn)題,請(qǐng)聯(lián)系我修改=。=

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/108659.html

相關(guān)文章

  • JavaScript中的拷貝與深拷貝

    摘要:所以,深拷貝是對(duì)對(duì)象以及對(duì)象的所有子對(duì)象進(jìn)行拷貝實(shí)現(xiàn)方式就是遞歸調(diào)用淺拷貝對(duì)于深拷貝的對(duì)象,改變?cè)磳?duì)象不會(huì)對(duì)得到的對(duì)象有影響。 上一篇 JavaScript中的繼承 前言 文章開(kāi)始之前,讓我們先思考一下這幾個(gè)問(wèn)題: 為什么會(huì)有淺拷貝與深拷貝 什么是淺拷貝與深拷貝 如何實(shí)現(xiàn)淺拷貝與深拷貝 好了,問(wèn)題出來(lái)了,那么下面就讓我們帶著這幾個(gè)問(wèn)題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯(cuò)誤之處...

    AZmake 評(píng)論0 收藏0
  • JavaScript中的拷貝與深拷貝

    摘要:所以,深拷貝是對(duì)對(duì)象以及對(duì)象的所有子對(duì)象進(jìn)行拷貝實(shí)現(xiàn)方式就是遞歸調(diào)用淺拷貝對(duì)于深拷貝的對(duì)象,改變?cè)磳?duì)象不會(huì)對(duì)得到的對(duì)象有影響。 為什么會(huì)有淺拷貝與深拷貝什么是淺拷貝與深拷貝如何實(shí)現(xiàn)淺拷貝與深拷貝好了,問(wèn)題出來(lái)了,那么下面就讓我們帶著這幾個(gè)問(wèn)題去探究一下吧! 如果文章中有出現(xiàn)紕漏、錯(cuò)誤之處,還請(qǐng)看到的小伙伴多多指教,先行謝過(guò) 以下↓ 數(shù)據(jù)類型在開(kāi)始了解 淺拷貝 與 深拷貝 之前,讓我們先...

    546669204 評(píng)論0 收藏0
  • JavaScript中的拷貝和深拷貝

    摘要:在中可以通過(guò)添加一個(gè)參數(shù)來(lái)實(shí)現(xiàn)遞歸,調(diào)用就可以實(shí)現(xiàn)一個(gè)深拷貝。利用序列化實(shí)現(xiàn)一個(gè)深拷貝 在JavaScript中,對(duì)于Object和Array這類引用類型值,當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型值時(shí),這個(gè)值的副本其實(shí)是一個(gè)指針,兩個(gè)變量指向同一個(gè)堆對(duì)象,改變其中一個(gè)變量,另一個(gè)也會(huì)受到影響。 這種拷貝分為兩種情況:拷貝引用和拷貝實(shí)例,也就是我們說(shuō)的淺拷貝和深拷貝 淺拷貝(shallow...

    ernest.wang 評(píng)論0 收藏0
  • JavaScript的深淺拷貝

    摘要:實(shí)際上,是禁止這樣做的。傳值和傳址基本數(shù)據(jù)類型賦值基本數(shù)據(jù)類型的賦值是在內(nèi)存中新開(kāi)辟一段棧內(nèi)存,然后再把再將值賦值到新的棧中。結(jié)果見(jiàn)輸出,可以看出來(lái),無(wú)論是修改賦值得到的對(duì)象和淺拷貝得到的都會(huì)改變?cè)紨?shù)據(jù)。 存儲(chǔ)問(wèn)題:深拷貝和淺拷貝的主要區(qū)別:在內(nèi)存中的存儲(chǔ)類型(堆和棧)不同堆:動(dòng)態(tài)分配的內(nèi)存,大小不定也不會(huì)自動(dòng)釋放棧:自動(dòng)分配的內(nèi)存,由系統(tǒng)自動(dòng)釋放數(shù)據(jù)類型: 基本數(shù)據(jù)類型: jav...

    zhjx922 評(píng)論0 收藏0
  • JavaScript的賦值、深拷貝和淺拷貝

    摘要:內(nèi)存空間分為兩種,棧內(nèi)存與堆內(nèi)存棧是系統(tǒng)自動(dòng)分配的內(nèi)存空間,由系統(tǒng)自動(dòng)釋放,堆則是動(dòng)態(tài)分配的內(nèi)存,大小不定不會(huì)自動(dòng)釋放。 JavaScript的內(nèi)存空間 在JavaScript中,每一個(gè)數(shù)據(jù)都需要一個(gè)內(nèi)存空間。內(nèi)存空間分為兩種,棧內(nèi)存(stack)與堆內(nèi)存(heap) 棧是系統(tǒng)自動(dòng)分配的內(nèi)存空間,由系統(tǒng)自動(dòng)釋放,堆則是動(dòng)態(tài)分配的內(nèi)存,大小不定不會(huì)自動(dòng)釋放。 基本數(shù)據(jù)類型 JavaScr...

    godlong_X 評(píng)論0 收藏0
  • JavaScript基礎(chǔ)心法——深淺拷貝

    摘要:原文地址基礎(chǔ)心法深淺拷貝歡迎。上面的代碼是最簡(jiǎn)單的利用賦值操作符實(shí)現(xiàn)了一個(gè)淺拷貝,可以很清楚的看到,隨著和改變,和也隨著發(fā)生了變化。展開(kāi)運(yùn)算符結(jié)論實(shí)現(xiàn)的是對(duì)象第一層的深拷貝。 原文地址:JavaScript基礎(chǔ)心法——深淺拷貝 歡迎star。 如果有錯(cuò)誤的地方歡迎指正。 淺拷貝和深拷貝都是對(duì)于JS中的引用類型而言的,淺拷貝就只是復(fù)制對(duì)象的引用,如果拷貝后的對(duì)象發(fā)生變化,原對(duì)象也會(huì)發(fā)生...

    keithxiaoy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<