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

資訊專欄INFORMATION COLUMN

ES6時代,你真的會克隆對象嗎?

xiaokai / 1700人閱讀

摘要:原文你真的會克隆對象嗎開始之前在開始聊克隆之前,我們還是先來看看數據類型。值通過函數生成,是獨一無二的。同時,中規定了對象的屬性名有兩種類型,一種是字符串,另一種就是類型。返回一個數組,包含對象自身的所有屬性的鍵名。

原文:你真的會克隆對象嗎

開始之前

在開始聊克隆之前,我們還是先來看看js數據類型。js的數據類型分為基本數據類型復雜數據類型

基本數據類型:Number、Boolean、String、Null、String、Symbol(ES6 新增)

復雜數據類型:Object,其他引用類型(Array、Date、RegExp、Function、基本包裝類型(Boolean、String、Number)、Math等)都是Object類型的實例對象

克隆:基本數據 => 復制這個變量;復雜數據 => 拷貝引用(網上的介紹很多,不深入了)

常見淺拷貝

對于對象的克隆,應該大多數人都能實現出來,可能深、淺拷貝都能想出好幾種方式,我們先來聊聊淺拷貝。

一個常見的淺拷貝一般是下面這樣:

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
}

或者更嚴謹一點的實現數組的判斷:

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

好像是沒什么問題呢,畢竟經過了好多項目的檢測,網上一搜就能出現一大堆。

但是,我們開頭介紹數據類型的時候就已經說過了,ES6新增了Symbol類型,情況好像就有點不一樣了

Symbol

Symbol是ES6中引入的原始數據類型。Symbol值通過Symbol函數生成,是獨一無二的。同時,ES6中規定了對象的屬性名有兩種類型,一種是字符串,另一種就是 Symbol 類型。凡是屬性名屬于 Symbol 類型,就不會與其他屬性名產生沖突。但是,隨之而來的問題是,我們的for...in循環不能遍歷出該屬性

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

Symbol類型,自然有遍歷Symbol類型的方法。Object.getOwnPropertySymbols + for...in的組合起來好像是能滿足我們要求的了。嗯,看起來還不錯,但是似乎有點麻煩了,有沒有更便捷一點的方式呢?或許新時代的男人---Reflect.ownKeys,要閃亮登場了,這個既能遍歷字符串,又能遍歷Symbol的死{{BANNED}}(請允許我這么夸他)。

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

這個時候熟悉ES6的人或許開始有疑問了,我們已經開始討論SymbolReflect.ownKeys,為什么淺克隆不直接用Object.assign或者展開運算符(...)呢?

嗯,待我吃根火腿冷靜冷靜,好像你說的很對!Object.assign的確是能拷貝Symbol類型的呢。但是呢,但是呢,我們是一個有追求的猿類,多一種實現方式不是能讓我們多了解一些坑嗎?而且這種方式不是能讓我們更靈活的實現不可預知的需求嗎?對,沒錯,是這樣子的...

Object.assign這個更完美的男人出來之后,好像淺拷貝部分也該結束了,正常來說,的確是這樣。不過我們再仔細想想上面的兩種方式,好像還是有點區別的呢。我們再來看看這兩個男人:

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

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

注意到了嗎?這里面有一個是否可枚舉的概念,這個時候是不是應該感慨我們知道怎么實現不可預知的需求了呢。

不可枚舉

我們先看個例子:

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}

唉,的確是這樣呢!看來Object.assign也不是我們的理想歸宿啊。我們再回過頭來看看Reflect.ownKeys,上面挖的坑也該填了,我們在講Symbol的時候,Object.getOwnPropertySymbols + for...in直接用Reflect.ownKeys替代了,在從可枚舉的角度出發看看,好像哪里不對,for...in只能循環遍歷對象自身的和繼承的可枚舉的屬性,且不含 Symbol。頭都大了嗎?來來來,喝完這杯,還有一杯,繼續接著來。這么多循環,我們來縷縷頭緒:

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

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

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

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

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

終于清晰了,或許也該結束了吧。

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

屬性描述符

我們在來思考一個例子:

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

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

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

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

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

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

寫到這里,淺拷貝部分也該結束了

結束語

可能實際項目中并不需要處理的這么細致,但是希望大家對各種遍歷、實現一個淺拷貝以及ES6的一些知識有一個總結和一點新的認識吧,本來想繼續寫深拷貝的,無賴篇幅已經不短,加上長夜漫漫,我想睡覺,深拷貝的問題更復雜,我先放放,日后再說。

最后的最后,對這篇文章有興趣的朋友,可以繼續關注下一篇的深克隆,會更新的會更新的...

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107076.html

相關文章

  • ES6時代真的克隆對象(二)

    摘要:多個窗口意味著多個全局環境,不同的全局環境擁有不同的全局對象,從而擁有不同的內置類型構造函數。比如,表達式會返回,因為屬性得到的僅僅是構造函數,而且是可以被手動更改的,只是返回的構造函數的名字,它并不返回類名。 原文:ES6時代,你真的會克隆對象嗎(二) 上一篇,我們從Symbol和是否可枚舉以及屬性描述符的角度分析了ES6下怎么淺拷貝一個對象,發表在掘金和segmentfault上(...

    BoYang 評論0 收藏0
  • 從-1開始的ES6探索之旅02:小伙子,對象咋來的?續篇 - 對象班(class)里來的?

    摘要:這是因為子類沒有自己的對象,而是繼承父類的對象,然后對其進行加工。 溫馨提示:作者的爬坑記錄,對你等大神完全沒有價值,別在我這浪費生命溫馨提示-續:你們要非得看,我也攔不住,但是至少得準備個支持ES6的Chrome瀏覽器吧?溫馨提示-再續:ES6簡直了,放著不用簡直令人發指! 書接上回,即便是程序員,也還是能夠通過自己的努力辛辛苦苦找到合適對象的,見前文《javascript對象不完全...

    incredible 評論0 收藏0
  • 白話es6系列二:真的聲明變量

    摘要:新增了二個聲明變量的關鍵字,和,再加上之前的,這樣聲明變量就有三個關鍵字了,大有三國鼎立之勢。當的值為時,該變量不會被聲明并初始化。如果上面的那個循環中用聲明變量,那么循環完了,變量也就隨時銷毀,不能再被訪問。 ES6新增了二個聲明變量的關鍵字,let和const,再加上ES6之前的var,這樣聲明變量就有三個關鍵字了,大有三國鼎立之勢。那到底用哪個來聲明變量呢? var 首先,得說說...

    maybe_009 評論0 收藏0
  • 真的知道JS

    摘要:你真的知道嗎是一門奇怪的語言,要真正掌握并不容易。廢話不多說,來一個快速測試,道題目,看看你對是否真正掌握。操作符用來判斷某個屬性屬于某個對象,可以是對象的直接屬性,也可以是通過繼承的屬性。很多人會認為打印的是。 你真的知道JavaScript嗎 ????JavaScript是一門奇怪的語言,要真正掌握并不容易。廢話不多說,來一個快速測試,5道題目,看看你對JavaScript是否真正...

    Half 評論0 收藏0
  • JavasScript重難點知識

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

    forsigner 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<