成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

ES6時(shí)代,你真的會(huì)克隆對(duì)象嗎?

xiaokai / 1723人閱讀

摘要:原文你真的會(huì)克隆對(duì)象嗎開(kāi)始之前在開(kāi)始聊克隆之前,我們還是先來(lái)看看數(shù)據(jù)類(lèi)型。值通過(guò)函數(shù)生成,是獨(dú)一無(wú)二的。同時(shí),中規(guī)定了對(duì)象的屬性名有兩種類(lèi)型,一種是字符串,另一種就是類(lèi)型。返回一個(gè)數(shù)組,包含對(duì)象自身的所有屬性的鍵名。

原文:你真的會(huì)克隆對(duì)象嗎

開(kāi)始之前

在開(kāi)始聊克隆之前,我們還是先來(lái)看看js數(shù)據(jù)類(lèi)型。js的數(shù)據(jù)類(lèi)型分為基本數(shù)據(jù)類(lèi)型復(fù)雜數(shù)據(jù)類(lèi)型。

基本數(shù)據(jù)類(lèi)型:Number、Boolean、String、Null、String、Symbol(ES6 新增)

復(fù)雜數(shù)據(jù)類(lèi)型:Object,其他引用類(lèi)型(Array、Date、RegExp、Function、基本包裝類(lèi)型(Boolean、String、Number)、Math等)都是Object類(lèi)型的實(shí)例對(duì)象

克隆:基本數(shù)據(jù) => 復(fù)制這個(gè)變量;復(fù)雜數(shù)據(jù) => 拷貝引用(網(wǎng)上的介紹很多,不深入了)

常見(jiàn)淺拷貝

對(duì)于對(duì)象的克隆,應(yīng)該大多數(shù)人都能實(shí)現(xiàn)出來(lái),可能深、淺拷貝都能想出好幾種方式,我們先來(lái)聊聊淺拷貝。

一個(gè)常見(jiàn)的淺拷貝一般是下面這樣:

function shallowCopy (obj) {
  if (typeof obj !== "object") {
    return
  }
  var newObj = obj instanceof Array ? [] : {}
  for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = obj[key]
    }
  }
  return newObj
}

或者更嚴(yán)謹(jǐn)一點(diǎn)的實(shí)現(xiàn)數(shù)組的判斷:

Object.prototype.toString.call(arr) === "[object Array]"

好像是沒(méi)什么問(wèn)題呢,畢竟經(jīng)過(guò)了好多項(xiàng)目的檢測(cè),網(wǎng)上一搜就能出現(xiàn)一大堆。

但是,我們開(kāi)頭介紹數(shù)據(jù)類(lèi)型的時(shí)候就已經(jīng)說(shuō)過(guò)了,ES6新增了Symbol類(lèi)型,情況好像就有點(diǎn)不一樣了

Symbol

Symbol是ES6中引入的原始數(shù)據(jù)類(lèi)型。Symbol值通過(guò)Symbol函數(shù)生成,是獨(dú)一無(wú)二的。同時(shí),ES6中規(guī)定了對(duì)象的屬性名有兩種類(lèi)型,一種是字符串,另一種就是 Symbol 類(lèi)型。凡是屬性名屬于 Symbol 類(lèi)型,就不會(huì)與其他屬性名產(chǎn)生沖突。但是,隨之而來(lái)的問(wèn)題是,我們的for...in循環(huán)不能遍歷出該屬性

Symbol 作為屬性名,該屬性不會(huì)出現(xiàn)在for...in、for...of循環(huán)中,也不會(huì)被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回。但是,它也不是私有屬性,有一個(gè)Object.getOwnPropertySymbols方法,可以獲取指定對(duì)象的所有 Symbol 屬性名。

Symbol類(lèi)型,自然有遍歷Symbol類(lèi)型的方法。Object.getOwnPropertySymbols + for...in的組合起來(lái)好像是能滿(mǎn)足我們要求的了。嗯,看起來(lái)還不錯(cuò),但是似乎有點(diǎn)麻煩了,有沒(méi)有更便捷一點(diǎn)的方式呢?或許新時(shí)代的男人---Reflect.ownKeys,要閃亮登場(chǎng)了,這個(gè)既能遍歷字符串,又能遍歷Symbol的死{{BANNED}}(請(qǐng)?jiān)试S我這么夸他)。

Reflect.ownKeys返回一個(gè)數(shù)組,包含對(duì)象自身的所有屬性,不管是屬性名是Symbol或字符串,也不管是否可枚舉
Object.assign

這個(gè)時(shí)候熟悉ES6的人或許開(kāi)始有疑問(wèn)了,我們已經(jīng)開(kāi)始討論SymbolReflect.ownKeys,為什么淺克隆不直接用Object.assign或者展開(kāi)運(yùn)算符(...)呢?

嗯,待我吃根火腿冷靜冷靜,好像你說(shuō)的很對(duì)!Object.assign的確是能拷貝Symbol類(lèi)型的呢。但是呢,但是呢,我們是一個(gè)有追求的猿類(lèi),多一種實(shí)現(xiàn)方式不是能讓我們多了解一些坑嗎?而且這種方式不是能讓我們更靈活的實(shí)現(xiàn)不可預(yù)知的需求嗎?對(duì),沒(méi)錯(cuò),是這樣子的...

Object.assign這個(gè)更完美的男人出來(lái)之后,好像淺拷貝部分也該結(jié)束了,正常來(lái)說(shuō),的確是這樣。不過(guò)我們?cè)僮屑?xì)想想上面的兩種方式,好像還是有點(diǎn)區(qū)別的呢。我們?cè)賮?lái)看看這兩個(gè)男人:

Reflect.ownKeys返回一個(gè)數(shù)組,包含對(duì)象自身的所有屬性,不管是屬性名是Symbol或字符串,也不管是否可枚舉

Object.assign拷貝的屬性是有限制的,只拷貝源對(duì)象的自身屬性(不拷貝繼承屬性),也不拷貝不可枚舉的屬性

注意到了嗎?這里面有一個(gè)是否可枚舉的概念,這個(gè)時(shí)候是不是應(yīng)該感慨我們知道怎么實(shí)現(xiàn)不可預(yù)知的需求了呢。

不可枚舉

我們先看個(gè)例子:

var obj = Object.create({ foo: 1 }, {
  [Symbol()]: {
    value: 1,
    enumerable: false
  },
  bar: {
    value: 2,
    enumerable: false
  },
  [Symbol()]: {
    value: 3,
    enumerable: true
  },
  baz: {
    value: 4,
    enumerable: true
  }
})

Object.assign({}, obj)  // {baz: 4, Symbol(): 3}

唉,的確是這樣呢!看來(lái)Object.assign也不是我們的理想歸宿啊。我們?cè)倩剡^(guò)頭來(lái)看看Reflect.ownKeys,上面挖的坑也該填了,我們?cè)谥vSymbol的時(shí)候,Object.getOwnPropertySymbols + for...in直接用Reflect.ownKeys替代了,在從可枚舉的角度出發(fā)看看,好像哪里不對(duì),for...in只能循環(huán)遍歷對(duì)象自身的和繼承的可枚舉的屬性,且不含 Symbol。頭都大了嗎?來(lái)來(lái)來(lái),喝完這杯,還有一杯,繼續(xù)接著來(lái)。這么多循環(huán),我們來(lái)縷縷頭緒:

for...in循環(huán)遍歷對(duì)象自身的和繼承的可枚舉屬性(不含 Symbol 屬性)。

Object.keys()返回一個(gè)數(shù)組,包括對(duì)象自身的(不含繼承的)所有可枚舉屬性(不含 Symbol 屬性)的鍵名。

Object.getOwnPropertyNames()返回一個(gè)數(shù)組,包含對(duì)象自身的所有屬性(不含 Symbol 屬性,但是包括不可枚舉屬性)的鍵名。

Object.getOwnPropertySymbols()返回一個(gè)數(shù)組,包含對(duì)象自身的所有 Symbol 屬性的鍵名。

Reflect.ownKeys()返回一個(gè)數(shù)組,包含對(duì)象自身的所有鍵名,不管鍵名是 Symbol 或字符串,也不管是否可枚舉。

終于清晰了,或許也該結(jié)束了吧。

慢著,好像上面的例子讓我想到了什么!??!

屬性描述符

我們?cè)趤?lái)思考一個(gè)例子:

const source = {
  get foo() { return 1 }
};
const target = {};

Object.assign(target, source) // { foo: 1 }

好像并不是我們想要的呢,遍歷的方式好像也不適用了,這可怎么辦。別急,還有Object.getOwnPropertyDescriptors可以用。

ES2017 引入了Object.getOwnPropertyDescriptors方法,返回指定對(duì)象所有自身屬性(非繼承屬性)的描述對(duì)象

仔細(xì)閱讀下文檔,終于用Object.getOwnPropertyDescriptors+Object.getPrototypeOf成功了呢

Object.create(
  Object.getPrototypeOf(obj), 
  Object.getOwnPropertyDescriptors(obj) 
)

寫(xiě)到這里,淺拷貝部分也該結(jié)束了

結(jié)束語(yǔ)

可能實(shí)際項(xiàng)目中并不需要處理的這么細(xì)致,但是希望大家對(duì)各種遍歷、實(shí)現(xiàn)一個(gè)淺拷貝以及ES6的一些知識(shí)有一個(gè)總結(jié)和一點(diǎn)新的認(rèn)識(shí)吧,本來(lái)想繼續(xù)寫(xiě)深拷貝的,無(wú)賴(lài)篇幅已經(jīng)不短,加上長(zhǎng)夜漫漫,我想睡覺(jué),深拷貝的問(wèn)題更復(fù)雜,我先放放,日后再說(shuō)。

最后的最后,對(duì)這篇文章有興趣的朋友,可以繼續(xù)關(guān)注下一篇的深克隆,會(huì)更新的會(huì)更新的...

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107076.html

相關(guān)文章

  • ES6時(shí)代真的會(huì)克隆對(duì)象(二)

    摘要:多個(gè)窗口意味著多個(gè)全局環(huán)境,不同的全局環(huán)境擁有不同的全局對(duì)象,從而擁有不同的內(nèi)置類(lèi)型構(gòu)造函數(shù)。比如,表達(dá)式會(huì)返回,因?yàn)閷傩缘玫降膬H僅是構(gòu)造函數(shù),而且是可以被手動(dòng)更改的,只是返回的構(gòu)造函數(shù)的名字,它并不返回類(lèi)名。 原文:ES6時(shí)代,你真的會(huì)克隆對(duì)象嗎(二) 上一篇,我們從Symbol和是否可枚舉以及屬性描述符的角度分析了ES6下怎么淺拷貝一個(gè)對(duì)象,發(fā)表在掘金和segmentfault上(...

    BoYang 評(píng)論0 收藏0
  • 從-1開(kāi)始的ES6探索之旅02:小伙子,對(duì)象咋來(lái)的?續(xù)篇 - 對(duì)象班(class)里來(lái)的?

    摘要:這是因?yàn)樽宇?lèi)沒(méi)有自己的對(duì)象,而是繼承父類(lèi)的對(duì)象,然后對(duì)其進(jìn)行加工。 溫馨提示:作者的爬坑記錄,對(duì)你等大神完全沒(méi)有價(jià)值,別在我這浪費(fèi)生命溫馨提示-續(xù):你們要非得看,我也攔不住,但是至少得準(zhǔn)備個(gè)支持ES6的Chrome瀏覽器吧?溫馨提示-再續(xù):ES6簡(jiǎn)直了,放著不用簡(jiǎn)直令人發(fā)指! 書(shū)接上回,即便是程序員,也還是能夠通過(guò)自己的努力辛辛苦苦找到合適對(duì)象的,見(jiàn)前文《javascript對(duì)象不完全...

    incredible 評(píng)論0 收藏0
  • 白話(huà)es6系列二:真的會(huì)聲明變量

    摘要:新增了二個(gè)聲明變量的關(guān)鍵字,和,再加上之前的,這樣聲明變量就有三個(gè)關(guān)鍵字了,大有三國(guó)鼎立之勢(shì)。當(dāng)?shù)闹禐闀r(shí),該變量不會(huì)被聲明并初始化。如果上面的那個(gè)循環(huán)中用聲明變量,那么循環(huán)完了,變量也就隨時(shí)銷(xiāo)毀,不能再被訪(fǎng)問(wèn)。 ES6新增了二個(gè)聲明變量的關(guān)鍵字,let和const,再加上ES6之前的var,這樣聲明變量就有三個(gè)關(guān)鍵字了,大有三國(guó)鼎立之勢(shì)。那到底用哪個(gè)來(lái)聲明變量呢? var 首先,得說(shuō)說(shuō)...

    maybe_009 評(píng)論0 收藏0
  • 真的知道JS?

    摘要:你真的知道嗎是一門(mén)奇怪的語(yǔ)言,要真正掌握并不容易。廢話(huà)不多說(shuō),來(lái)一個(gè)快速測(cè)試,道題目,看看你對(duì)是否真正掌握。操作符用來(lái)判斷某個(gè)屬性屬于某個(gè)對(duì)象,可以是對(duì)象的直接屬性,也可以是通過(guò)繼承的屬性。很多人會(huì)認(rèn)為打印的是。 你真的知道JavaScript嗎 ????JavaScript是一門(mén)奇怪的語(yǔ)言,要真正掌握并不容易。廢話(huà)不多說(shuō),來(lái)一個(gè)快速測(cè)試,5道題目,看看你對(duì)JavaScript是否真正...

    Half 評(píng)論0 收藏0
  • JavasScript重難點(diǎn)知識(shí)

    摘要:忍者級(jí)別的函數(shù)操作對(duì)于什么是匿名函數(shù),這里就不做過(guò)多介紹了。我們需要知道的是,對(duì)于而言,匿名函數(shù)是一個(gè)很重要且具有邏輯性的特性。通常,匿名函數(shù)的使用情況是創(chuàng)建一個(gè)供以后使用的函數(shù)。 JS 中的遞歸 遞歸, 遞歸基礎(chǔ), 斐波那契數(shù)列, 使用遞歸方式深拷貝, 自定義事件添加 這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制 本文的目的就是要保證你徹底弄懂javascript的執(zhí)行機(jī)制,如果...

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

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

0條評(píng)論

閱讀需要支付1元查看
<