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

資訊專(zhuān)欄INFORMATION COLUMN

Javascript的對(duì)象拷貝

simpleapples / 3242人閱讀

摘要:的對(duì)象只是指向內(nèi)存中某個(gè)位置的指針。所以在拷貝中的對(duì)象時(shí),要根據(jù)實(shí)際情況做一些考慮。結(jié)論中最好的對(duì)象拷貝的算法,很大程度上取決于其使用環(huán)境,以及你需要拷貝的對(duì)象類(lèi)型。

翻譯:瘋狂的技術(shù)宅
原文:https://smalldata.tech/blog/2...

本文首發(fā)微信公眾號(hào):前端先鋒
歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章

在開(kāi)始之前,我先普及一些基礎(chǔ)知識(shí)。Javascript 的對(duì)象只是指向內(nèi)存中某個(gè)位置的指針。這些指針是可變的,也就是說(shuō),它們可以重新被賦值。所以?xún)H僅復(fù)制這個(gè)指針,其結(jié)果是有兩個(gè)指針指向內(nèi)存中的同一個(gè)地址。

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?    

通過(guò)上面的例子可以看到,對(duì)象 foo 和 bar 都能隨著對(duì)方的變化而變化。所以在拷貝 Javascript 中的對(duì)象時(shí),要根據(jù)實(shí)際情況做一些考慮。

淺拷貝

如果要操作的對(duì)象擁有的屬性都是值類(lèi)型,那么可以使用擴(kuò)展語(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è)不同來(lái)源對(duì)象中的屬性復(fù)制到一個(gè)目標(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ì)象,那么實(shí)際被拷貝的只是那些指針,這跟執(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 } }
深拷貝(有限制)

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

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

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

深拷貝 (限制較少)

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

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

Via 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();

Via the history API:history.pushState()history.replaceState() 都會(huì)給它們的第一個(gè)參數(shù)做一個(gè)結(jié)構(gòu)化克隆!需要注意的是,此方法是同步的,因?yàn)閷?duì)瀏覽器歷史記錄進(jìn)行操作的速度不是很快,假如頻繁調(diào)用這個(gè)方法,將會(huì)導(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)建一個(gè) notification 實(shí)例的時(shí)候,構(gòu)造器為它相關(guān)的數(shù)據(jù)做了結(jié)構(gòu)化克隆。需要注意的是,它會(huì)嘗試向用戶(hù)展示瀏覽器通知,但是除非它收到了用戶(hù)允許展示通知的請(qǐng)求,否則它什么都不會(huì)做。一旦用戶(hù)點(diǎn)擊同意的話(huà),notification 會(huì)立刻被關(guān)閉。

const structuredClone = obj => {
  const n = new Notification("", {data: obj, silent: true});
  n.onshow = n.close.bind(n);
  return n.data;
};
用 Node.js 進(jìn)行深拷貝

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

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

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

我很期待可以隨便使用結(jié)構(gòu)化克隆的那一天的到來(lái),讓對(duì)象拷貝不再令人頭疼^_^

本文首發(fā)微信公眾號(hào):前端先鋒 歡迎掃描二維碼關(guān)注公眾號(hào),每天都給你推送新鮮的前端技術(shù)文章

歡迎繼續(xù)閱讀本專(zhuān)欄其它高贊文章:

12個(gè)令人驚嘆的CSS實(shí)驗(yàn)項(xiàng)目

必須要會(huì)的 50 個(gè)React 面試題

世界頂級(jí)公司的前端面試都問(wèn)些什么

11 個(gè)最好的 JavaScript 動(dòng)態(tài)效果庫(kù)

CSS Flexbox 可視化手冊(cè)

從設(shè)計(jì)者的角度看 React

過(guò)節(jié)很無(wú)聊?還是用 JavaScript 寫(xiě)一個(gè)腦力小游戲吧!

CSS粘性定位是怎樣工作的

一步步教你用HTML5 SVG實(shí)現(xiàn)動(dòng)畫(huà)效果

程序員30歲前月薪達(dá)不到30K,該何去何從

14個(gè)最好的 JavaScript 數(shù)據(jù)可視化庫(kù)

8 個(gè)給前端的頂級(jí) VS Code 擴(kuò)展插件

Node.js 多線(xiàn)程完全指南

把HTML轉(zhuǎn)成PDF的4個(gè)方案及實(shí)現(xiàn)

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/103636.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基礎(chǔ)心法——深淺拷貝

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

    keithxiaoy 評(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ù)類(lèi)型在開(kāi)始了解 淺拷貝 與 深拷貝 之前,讓我們先...

    546669204 評(píng)論0 收藏0
  • JavaScript專(zhuān)題之深淺拷貝

    摘要:專(zhuān)題系列第六篇,講解深淺拷貝的技巧和以及實(shí)現(xiàn)深淺拷貝的思路前言拷貝也是面試經(jīng)典吶數(shù)組的淺拷貝如果是數(shù)組,我們可以利用數(shù)組的一些方法比如返回一個(gè)新數(shù)組的特性來(lái)實(shí)現(xiàn)拷貝。所以我們可以看出使用和是一種淺拷貝。 JavaScript 專(zhuān)題系列第六篇,講解深淺拷貝的技巧和以及實(shí)現(xiàn)深淺拷貝的思路 前言 拷貝也是面試經(jīng)典吶! 數(shù)組的淺拷貝 如果是數(shù)組,我們可以利用數(shù)組的一些方法比如:slice、co...

    RancherLabs 評(píng)論0 收藏0
  • JavaScript系列--淺析JavaScript解析賦值、淺拷貝和深拷貝區(qū)別

    摘要:它將返回目標(biāo)對(duì)象。有些文章說(shuō)是深拷貝,其實(shí)這是不正確的。深拷貝相比于淺拷貝速度較慢并且花銷(xiāo)較大。拷貝前后兩個(gè)對(duì)象互不影響。使用深拷貝的場(chǎng)景完全改變變量之后對(duì)沒(méi)有任何影響,這就是深拷貝的魔力。 一、賦值(Copy) 賦值是將某一數(shù)值或?qū)ο筚x給某個(gè)變量的過(guò)程,分為: 1、基本數(shù)據(jù)類(lèi)型:賦值,賦值之后兩個(gè)變量互不影響 2、引用數(shù)據(jù)類(lèi)型:賦址,兩個(gè)變量具有相同的引用,指向同一個(gè)對(duì)象,相互之間有...

    laznrbfe 評(píng)論0 收藏0
  • Day14 - JavaScript 引用和值拷貝

    摘要:引用和值拷貝微信公眾號(hào)開(kāi)發(fā)企業(yè)級(jí)產(chǎn)品全棧開(kāi)發(fā)速成周末班首期班號(hào)正式開(kāi)班,歡迎搶座作者黎躍春追時(shí)間的人簡(jiǎn)介是推出的一個(gè)天挑戰(zhàn)。深拷貝與淺拷貝對(duì)比創(chuàng)建對(duì)象黎躍春淺拷貝深拷貝將對(duì)象轉(zhuǎn)換成字符串,打印時(shí)效果清晰。 Day14 - JavaScript 引用和值拷貝 (Node+Vue+微信公眾號(hào)開(kāi)發(fā))企業(yè)級(jí)產(chǎn)品全棧開(kāi)發(fā)速成周末班首期班(10.28號(hào)正式開(kāi)班,歡迎搶座) 作者:?黎躍春-追時(shí)間的...

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

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

0條評(píng)論

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