真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Javascript中怎么實現(xiàn)對象的拷貝

Javascript中怎么實現(xiàn)對象的拷貝,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

成都創(chuàng)新互聯(lián)公司是專業(yè)的璧山網(wǎng)站建設(shè)公司,璧山接單;提供成都做網(wǎng)站、網(wǎng)站建設(shè),網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行璧山網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊,希望更多企業(yè)前來合作!

在開始之前,我先普及一些基礎(chǔ)知識。Javascript  的對象只是指向內(nèi)存中某個位置的指針。這些指針是可變的,也就是說,它們可以重新被賦值。所以僅僅復(fù)制這個指針,其結(jié)果是有兩個指針指向內(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 都能隨著對方的變化而變化。所以在拷貝 Javascript  中的對象時,要根據(jù)實際情況做一些考慮。

淺拷貝

如果要操作的對象擁有的屬性都是值類型,那么可以使用擴(kuò)展語法或 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" }

可以看到上面兩種方法都可以把多個不同來源對象中的屬性復(fù)制到一個目標(biāo)對象中。

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" }

上面這種方法是存在問題的,如果對象的屬性也是對象,那么實際被拷貝的只是那些指針,這跟執(zhí)行 var bar = foo;  的效果是一樣的,和第一段代碼中的做法一樣。

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 } }

深拷貝(有限制)

想要對一個對象進(jìn)行深拷貝,一個可行的方法是先把對象序列化為字符串,然后再對它進(jìn)行反序列化。

var obj = { a: 0, b: { c: 0 } }; var copy = JSON.parse(JSON.stringify(obj));

不幸的是,這個方法只在對象中包含可序列化值,同時沒有循環(huán)引用的情況下適用。常見的不能被序列化的就是日期對象 —— 盡管它顯示的是字符串化的 ISO  日期格式,但是 JSON.parse 只會把它解析成為一個字符串,而不是日期類型。

深拷貝 (限制較少)

對于一些更復(fù)雜的場景,我們可以用 HTML5 提供的一個名為結(jié)構(gòu)化克隆的新算法。不過,截至本文發(fā)布為止,有些內(nèi)置類型仍然無法支持,但與  JSON.parse 相比較而言,它支持的類型要多的多:Date、RegExp、 Map、 Set、 Blob、 FileList、 ImageData、  sparse 和 typed Array。它還維護(hù)了克隆對象的引用,這使它可以支持循環(huán)引用結(jié)構(gòu)的拷貝,而這些在前面所說的序列化中是不支持的。

目前還沒有直接調(diào)用結(jié)構(gòu)化克隆的方法,但是有些新的瀏覽器特性的底層用了這個算法。所以深拷貝對象可能需要依賴一系列的環(huán)境才能實現(xiàn)。

Via MessageChannels: 其原理是借用了通信中用到的序列化算法。由于它是基于事件的,所以這里的克隆也是一個異步操作。

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() };   originaloriginal.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();

Via the history API:history.pushState() 和  history.replaceState()都會給它們的第一個參數(shù)做一個結(jié)構(gòu)化克隆!需要注意的是,此方法是同步的,因為對瀏覽器歷史記錄進(jìn)行操作的速度不是很快,假如頻繁調(diào)用這個方法,將會導(dǎo)致瀏覽器卡死。

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

Via notification API:當(dāng)創(chuàng)建一個 notification  實例的時候,構(gòu)造器為它相關(guān)的數(shù)據(jù)做了結(jié)構(gòu)化克隆。需要注意的是,它會嘗試向用戶展示瀏覽器通知,但是除非它收到了用戶允許展示通知的請求,否則它什么都不會做。一旦用戶點擊同意的話,notification  會立刻被關(guān)閉。

const structuredClone = obj => {   const n = new Notification("", {data: obj, silent: true});   nn.onshow = n.close.bind(n);   return n.data; };

用 Node.js 進(jìn)行深拷貝

Node.js 的 8.0.0 版本提供了一個 序列化 api 可以和結(jié)構(gòu)化克隆相媲美. 不過這個 API  在本文發(fā)布的時候,還只是被標(biāo)記為試驗性的:

const v8 = require('v8'); const buf = v8.serialize({a: 'foo', b: new Date()}); const cloned = v8.deserialize(buf); cloned.b.getMonth();

在 8.0.0 版本以下比較穩(wěn)定的方法,可以考慮用 lodash 的 cloneDeep函數(shù),它的思想多少也基于結(jié)構(gòu)化克隆算法。

結(jié)論

Javascript 中最好的對象拷貝的算法,很大程度上取決于其使用環(huán)境,以及你需要拷貝的對象類型。雖然 lodash  是最安全的泛型深拷貝函數(shù),但是如果你自己封裝的話,也許能夠獲得效率更高的實現(xiàn)方法,以下就是一個簡單的深拷貝,對 Date 日期對象也同樣適用:

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); }

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。


文章題目:Javascript中怎么實現(xiàn)對象的拷貝
轉(zhuǎn)載來源:http://weahome.cn/article/pjgjdc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部