在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美

當前位置:雨林木風下載站 > 網頁設計教程 > 詳細頁面

Immutable.js源碼之List 分類的詳細解析(附示例)

Immutable.js源碼之List 分類的詳細解析(附示例)

更新時間:2025-12-08 文章作者:未知 信息來源:網絡 閱讀次數:

網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立...
網頁的本質就是超級文本標記語言,通過結合使用其他的Web技術(如:腳本語言、公共網關接口、組件等),可以創造出功能強大的網頁。因而,超級文本標記語言是萬維網(Web)編程的基礎,也就是說萬維網是建立在超文本基礎之上的。超級文本標記語言之所以稱為超文本標記語言,是因為文本中包含了所謂“超級鏈接”點。
本篇文章給大家帶來的內容是關于Immutable.js源碼之List 類型的詳細解析(附示例),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。

一、存儲圖解

我以下面這段代碼為例子,畫出這個List的存儲結構:

let myList = [];
for(let i=0;i<1100;i++) {
    myList[i] = i;
}
debugger;//可以在這里打個斷點調試
let immutableList = Immutable.List(myList)
debugger;
console.log(immutableList.set(1000, 'Remm'));
debugger;
console.log(immutableList.get(1000));

403292043-5bf921fa7c00f_articlex.png

二、vector trie 的構建過程

我們用上面的代碼為例子一步一步的解析。首先是把原生的list轉換為inmutable的list 類型:

export class List extends IndexedCollection {
  // @pragma Construction

  constructor(value) { // 此時的value就是上面的myList數組
    const empty = emptyList();
    if (value === null || value === undefined) {//判斷是否為空
      return empty;
    }
    if (isList(value)) {//判斷是否已經是imutable的list類型
      return value;
    }
    const iter = IndexedCollection(value);//序列化數組
    const size = iter.size;
    if (size === 0) {
      return empty;
    }
    assertNotInfinite(size);
    if (size > 0 && size < SIZE) { // 判斷size是否超過32
      return makeList(0, size, SHIFT, null, new VNode(iter.toArray()));
    }
    return empty.withMutations(list => {
      list.setSize(size);
      iter.forEach((v, i) => list.set(i, v));
    });
  }

  。。。。。。

}

首先會創建一個空的list

let EMPTY_LIST;
export function emptyList() {
  return EMPTY_LIST || (EMPTY_LIST = makeList(0, 0, SHIFT));
}

SHIFT的值為5,export const SHIFT = 5; // Resulted in best performance after ______?

再繼續看makeList,可以清晰看到 List 的主要部分:

function makeList(origin, capacity, level, root, tail, ownerID, hash) {
  const list = Object.create(ListPrototype);
  list.size = capacity - origin;// 數組的長度
  list._origin = origin;// 數組的起始位置 一般是0
  list._capacity = capacity;// 數組容量 等于 size
  list._level = level;//樹的深度,為0時是葉子結點。默認值是5,存儲指數部分,用于方便位運算,增加一個深度,level值+5
  list._root = root;// trie樹實現
  list._tail = tail;// 32個為一組,存放最后剩余的數據 其實就是 %32
  list.__ownerID = ownerID;
  list.__hash = hash;
  list.__altered = false;
  return list;
}

將傳入的數據序列化

// ArraySeq
iter = {
size: 數組的length,
_array: 傳入數組的引用
}

判斷size是否超過32,size > 0 && size < SIZE 這里 SIZE : export const SIZE = 1 << SHIFT;即 32。若沒有超過32,所有數據都放在_tail中。

_root 和 _tail 里面的數據又有以下結構:

// @VNode class
constructor(array, ownerID) {
  this.array = array;
  this.ownerID = ownerID;
}

可以這樣調試查看:

let myList = [];
for(let i=0;i<30;i++) {
    myList[i] = i;
}
debugger;//可以在這里打個斷點調試
console.log(Immutable.List(myList));

size如果超過32

return empty.withMutations(list => {
    list.setSize(size);//構建樹的結構 主要是計算出樹的深度
    iter.forEach((v, i) => list.set(i, v));//填充好數據
});
export function withMutations(fn) {
  const mutable = this.asMutable();
  fn(mutable);
  return mutable.wasAltered() ? mutable.__ensureOwner(this.__ownerID) : this;
}

list.setSize(size)中有一個重要的方法setListBounds,下面我們主要看這個方法如何構建這顆樹

這個方法最主要的作用是 確定 list的level

function setListBounds(list, begin, end) {

  ......
  
  const newTailOffset = getTailOffset(newCapacity);

  // New size might need creating a higher root.
  // 是否需要增加數的深度 把 1 左移 newLevel + SHIFT 位 相當于 1 * 2 ^ (newLevel + SHIFT)
  // 以 size為 1100 為例子 newTailOffset的值為1088 第一次 1088 > 2 ^ 10 樹增加一層深度
  // 第二次 1088 < 2 ^ 15 跳出循環 newLevel = 10
  while (newTailOffset >= 1 << (newLevel + SHIFT)) {
    newRoot = new VNode(
      newRoot && newRoot.array.length ? [newRoot] : [],
      owner
    );
    newLevel += SHIFT;
  }

  ......
}
function getTailOffset(size) {
    // (1100 - 1) / 2^5 % 2^5 = 1088
    return size < SIZE ? 0 : (((size - 1) >>> SHIFT) << SHIFT);
}

經過 list.setSize(size);構建好的結構

103067300-5bf9243f80ba3_articlex.png

三、set 方法

listiter.forEach((v, i) => list.set(i, v));這里是將iter中的_array填充到

這里主要還是看看set方法如何設置數據

set(index, value) {
    return updateList(this, index, value);
}
function updateList(list, index, value) {
  ......
  if (index >= getTailOffset(list._capacity)) {
    newTail = updateVNode(newTail, list.__ownerID, 0, index, value, didAlter);
  } else {
    newRoot = updateVNode(
      newRoot,
      list.__ownerID,
      list._level,
      index,
      value,
      didAlter
    );
  }

  ......

}
function updateVNode(node, ownerID, level, index, value, didAlter) {
  // 根據 index 和 level 計算 數據set的位置在哪
  const idx = (index >>> level) & MASK;

  // 利用遞歸 一步一步的尋找位置 直到找到最終的位置
  if (level > 0) {
    const lowerNode = node && node.array[idx];
    const newLowerNode = updateVNode(
      lowerNode,
      ownerID,
      level - SHIFT,
      index,
      value,
      didAlter
    );
    ......
    // 把node節點的array復制一份生成一個新的節點newNode editableVNode函數見下面源碼
    newNode = editableVNode(node, ownerID);
    // 回溯階段將 子節點的引用賦值給自己
    newNode.array[idx] = newLowerNode;
    return newNode;
  }
  ......
  newNode = editableVNode(node, ownerID);
  // 當遞歸到葉子節點 也就是level <= 0 將值放到這個位置
  newNode.array[idx] = value;
  ......
  return newNode;
}
function editableVNode(node, ownerID) {
  if (ownerID && node && ownerID === node.ownerID) {
    return node;
  }
  return new VNode(node ? node.array.slice() : [], ownerID);
}

下面我們看看運行了一次set(0,0)的結果

2031164043-5bf925476793e_articlex.png

整個結構構建完之后

3123768613-5bf92586ec334_articlex.png

下面我們接著看剛剛我們構建的list set(1000, 'Remm'),其實所有的set的源碼上面已經解析過了,我們再來溫習一下。

調用上面的set方法,index=1000,value='Remm'。調用updateList,繼而調用updateVNode。通過const idx = (index >>> level) & MASK;計算要尋找的節點的位置(在這個例子中,idx的值依次是0->31->8)。 不斷的遞歸查找,當 level <= 0 到達遞歸的終止條件,其實就是達到樹的葉子節點,此時通過newNode = editableVNode(node, ownerID);創建一個新的節點,然后 newNode.array[8] = 'Remm'。接著就是開始回溯,在回溯階段,自己把自己克隆一個,newNode = editableVNode(node, ownerID);,注意這里克隆的只是引用,所以不是深拷貝。然后再將idx位置的更新了的子節點重新賦值,newNode.array[idx] = newLowerNode;,這樣沿著路徑一直返回,更新路徑上的每個節點,最后得到一個新的根節點。

更新后的list:

2289781780-5bf925c1e53da_articlex.png

四、get 方法

了解完上面的list構建和set,我們再來看 immutableList.get(1000) 源碼就是小菜一碟了。

  get(index, notSetValue) {
    index = wrapIndex(this, index);
    if (index >= 0 && index < this.size) {
      index += this._origin;
      const node = listNodeFor(this, index);
      return node && node.array[index & MASK];
    }
    return notSetValue;
  }
function listNodeFor(list, rawIndex) {
  if (rawIndex >= getTailOffset(list._capacity)) {
    return list._tail;
  }
  if (rawIndex < 1 << (list._level + SHIFT)) {
    let node = list._root;
    let level = list._level;
    while (node && level > 0) {
      // 循環查找節點所在位置
      node = node.array[(rawIndex >>> level) & MASK];
      level -= SHIFT;
    }
    return node;
  }
}

五、tire 樹 的優點

來一張從網上盜來的圖:

1233025053-5bf927fee8cdb_articlex.png

這種樹的數據結構(tire 樹),保證其拷貝引用的次數降到了最低,就是通過極端的方式,大大降低拷貝數量,一個擁有100萬條屬性的對象,淺拷貝需要賦值 99.9999萬次,而在 tire 樹中,根據其訪問的深度,只有一個層級只需要拷貝 31 次,這個數字不隨著對象屬性的增加而增大。而隨著層級的深入,會線性增加拷貝數量,但由于對象訪問深度不會特別高,10 層已經幾乎見不到了,因此最多拷貝300次,速度還是非常快的。

我上面所解析的情況有 構建、修改、查詢。其實還有 添加 和 刪除。

以上就是Immutable.js源碼之List 類型的詳細解析(附示例)的詳細內容,更多請關注php中文網其它相關文章!


網站建設是一個廣義的術語,涵蓋了許多不同的技能和學科中所使用的生產和維護的網站。

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統下載排行

在线看毛片视频-国产免费av在线-欧美日韩一区二区三区-国产成人无码av在线播放无广告-亚洲人va欧美va人人爽-国产第一草草-西班牙黄色片-四虎在线网站8848-最新av片免费网站入口-东京热无码中文字幕av专区-日本大人吃奶视频xxxx-欧美精品一区二区三区四区五区-国产片天天弄-国产免费内射又粗又爽密桃视频-欧美爱爱网站-日韩v欧美
  • <li id="86scu"><menu id="86scu"></menu></li>
    <li id="86scu"></li>
    <button id="86scu"></button>
  • <s id="86scu"></s><button id="86scu"><menu id="86scu"></menu></button>
  • 日本在线观看a| 少妇高清精品毛片在线视频| 国产亚洲天堂网| 糖心vlog在线免费观看| 五月花丁香婷婷| 超碰超碰在线观看| 男女污污的视频| 在线视频观看91| 欧美专区第二页| 在线观看污视频| www.九色.com| 国产手机免费视频| 天天夜碰日日摸日日澡性色av| www.-级毛片线天内射视视| 爱爱爱视频网站| 久久久天堂国产精品| 成人性免费视频| 黄色免费视频大全| 亚洲人辣妹窥探嘘嘘| 日韩av片免费观看| 精品91一区二区三区| 久久久99精品视频| 国产一区亚洲二区三区| 超碰网在线观看| www.污污视频| 欧美在线观看黄| 成人av一级片| 91丨九色丨蝌蚪| av在线com| 一路向西2在线观看| 日本在线视频www色| 日本不卡在线观看视频| 亚洲综合在线一区二区| 妞干网在线观看视频| 在线视频日韩一区| www.日本三级| xx欧美撒尿嘘撒尿xx| 人人妻人人澡人人爽欧美一区双| 无码aⅴ精品一区二区三区浪潮 | 农民人伦一区二区三区| 亚洲熟妇av一区二区三区| 欧美一级视频在线| 欧美精品自拍视频| 午夜免费福利网站| www.国产区| 久久艹国产精品| 网站在线你懂的| 99草草国产熟女视频在线| 一级黄色录像免费看| 久久婷婷综合色| 国产一区亚洲二区三区| 成人区一区二区| 麻豆md0077饥渴少妇| 手机在线成人免费视频| 国产1区2区在线| 无码人妻丰满熟妇区96| 8x8ⅹ国产精品一区二区二区| 免费看国产黄色片| 欧美污视频网站| 黄色片一级视频| 成年人午夜免费视频| 国产女主播av| 7777在线视频| 午夜免费一级片| 中文字幕综合在线观看| 久久撸在线视频| 午夜视频在线网站| 亚洲综合欧美激情| 久久久久xxxx| www.午夜av| 视色,视色影院,视色影库,视色网 日韩精品福利片午夜免费观看 | 欧美日韩一区二区三区69堂| 久久久久免费精品| 热久久精品免费视频| 久久久久久久久久久久久久国产| 免费一级特黄毛片| 男女超爽视频免费播放| 国产精彩免费视频| 国产精品亚洲a| 国产一伦一伦一伦| 国产女同无遮挡互慰高潮91| 欧美成人手机在线视频| 善良的小姨在线| 欧洲精品一区二区三区久久| 麻豆tv在线播放| 少妇黄色一级片| 欧美性受xxxx黒人xyx性爽| 免费极品av一视觉盛宴| 又大又硬又爽免费视频| 久久综合九色综合88i| 999在线免费视频| 天美一区二区三区| 99色这里只有精品| 天天操天天爱天天爽| 日韩精品手机在线观看| 毛片一区二区三区四区| 婷婷激情综合五月天| 你懂的av在线| 黄色一级片网址| 欧美成人黑人猛交| 久久香蕉视频网站| 免费看污污网站| 91传媒免费视频| 毛片毛片毛片毛片毛片毛片毛片毛片毛片 | 爽爽爽在线观看| 日本少妇高潮喷水视频| www激情五月| 免费观看精品视频| 国产一二三四区在线观看| 日韩手机在线观看视频| 中文字幕日韩精品无码内射| 992kp快乐看片永久免费网址| 4444在线观看| 午夜免费看毛片| 男人揉女人奶房视频60分| 亚洲区成人777777精品| 一本岛在线视频| 欧美日韩一区二区在线免费观看 | 国产专区在线视频| 亚洲欧美日韩三级| 国产一级特黄a大片免费| 欧美视频在线观看网站| 91免费网站视频| 污污视频在线免费| 一起操在线视频| 91香蕉视频导航| 亚洲天堂av线| 欧美视频第三页| a在线视频观看| 91成人在线观看喷潮教学| 免费网站在线观看视频| 国产卡一卡二在线| 米仓穗香在线观看| 久久最新免费视频| 国产在线拍揄自揄拍无码| 国产奶头好大揉着好爽视频| 香蕉视频在线网址| 国产日韩第一页| 免费人成自慰网站| 大j8黑人w巨大888a片| 大胆欧美熟妇xx| 好吊妞无缓冲视频观看| 成人av一级片| 亚洲欧美自拍另类日韩| 天堂网成人在线| 手机看片日韩国产| 成年丰满熟妇午夜免费视频| 黄色一级片国产| 麻豆av免费在线| 嫩草视频免费在线观看| 粉嫩av一区二区三区天美传媒| 看一级黄色录像| 成人av在线不卡| 在线观看免费成人av| wwwwwxxxx日本| 咪咪色在线视频| 给我免费播放片在线观看| 久久网站免费视频| 日韩小视频网站| 日韩一级片播放| 中文字幕第三区| 日韩欧美在线播放视频| 九九久久久久久| av网站手机在线观看| 国产一二三区av| 800av在线免费观看| 精品免费国产一区二区| 交换做爰国语对白| 成年人免费大片| a级免费在线观看| 狠狠操狠狠干视频| 国产aaa一级片| 欧美一级中文字幕| 国产视频1区2区3区| 日本午夜激情视频| 国产美女视频免费看| 国产91在线视频观看| 日本免费黄色小视频| 天天看片天天操| www.欧美日本| 青青草原av在线播放| 屁屁影院ccyy国产第一页| 亚洲免费av一区二区三区| www.日本在线播放| 国内自拍中文字幕| 免费不卡av网站| 日韩欧美国产片| 天天干天天玩天天操| 麻豆传传媒久久久爱| 亚洲爆乳无码专区| 国产精品国产亚洲精品看不卡| 日本a在线天堂| 米仓穗香在线观看| 97精品国产97久久久久久粉红| 中文字幕免费高清在线| 蜜臀av免费观看| 最新国产黄色网址| 亚洲免费黄色录像| 欧美xxxxxbbbbb| 国产精品视频一二三四区|