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

資訊專欄INFORMATION COLUMN

What's New in JavaScript

cgh1999520 / 1740人閱讀

摘要:在和中都保留了數組的強引用,所以在中簡單的清除變量內存并沒有得到釋放,因為還存在引用計數。而在中,它的鍵是弱引用,不計入引用計數中,所以當被清除之后,數組會因為引用計數為而被回收掉。其實我們主要注意的引用是不計引用計數的,就好理解了。

前幾天 Google IO 上 V8 團隊為我們分享了《What"s New in JavaScript》主題,分享的語速很慢推薦大家可以都去聽聽就當鍛煉下聽力了。看完之后我整理了一個文字版幫助大家快速了解分享內容,嘉賓主要是分享了以下幾點:

JS 解析快了 2 倍

async 執行快了 11 倍

平均減少了 20% 的內存使用

class fileds 可以直接在 class 中初始化變量不用寫在 constructor 里

私有變量前綴

string.matchAll 用來做正則多次匹配

numeric seperator 允許我們在寫數字的時候使用 _ 作為分隔符提高可讀性

bigint 新的大數字類型支持

Intl.NumberFormat 本地化格式化數字顯示

Array.prototype.flat(), Array.prototype.flatMap() 多層數組打平方法

Object.entries() 和 Object.fromEntries() 快速對對象進行數組操作

globalThis 無環境依賴的全局 this 支持

Array.prototype.sort() 的排序結果穩定輸出

Intl.RelativeTimeFormat(), Intl.DateTimeFormat() 本地化顯示時間

Intl.ListFormat() 本地化顯示多個名詞列表

Intl.locale() 提供某一本地化語言的各種常量查詢

頂級 await 無需寫 async 的支持

Promise.allSettled() 和 Promise.any() 的增加豐富 Promise 場景

WeakRef 類型用來做部分變量弱引用減少內存泄露

Async 執行比之前快了11倍

開場就用 11x faster 數字把大家驚到了,也有很多同學好奇到底是怎么做到的。其實這個優化并不是最近做的,去年11月的時候 V8 團隊就發了一篇文章 《Faster async functions and promises》,這里面就非常詳盡的講述了如何讓 async/await 優化到這個速度的,其主要歸功于以下三點:

TurboFan:新的 JS 編譯器

Orinoco:新的 GC 引擎

Node.js 8 上的一個 await bug

2008年 Chrome 出世,10年 Chrome 引入了 Crankshaft 編譯器,多年后的今天這員老將已經無法滿足現有的優化需求,畢竟當時的作者也未曾料想到前端的世界會發展的這么快。關于為何使用 TurboFan 替換掉 Crankshaft,大家可以看看《Launching Ignition and TurboFan》,原文中是這么說的:

Crankshaft 僅支持優化 JavaScript 的一部分特性。它并沒有通過結構化的異常處理來設計代碼,即代碼塊并沒有通過try、catch、finally等關鍵字劃分。另外由于為每一個新的特性Cranksshaft都將要做九套不同的框架代碼適應不同的平臺,因此在適配新的Javascript語言特性也很困難。還有Crankshaft框架代碼的設計也限制優化機器碼的擴展。盡管V8引擎團隊為每一套芯片架構維護超過一萬行代碼,Crankshaft也不過為Javascript擠出一點點性能。
via:《Javascript是如何工作的:V8引擎的內核Ignition和TurboFan》

而 TurboFan 則提供了更好的架構,能夠在不修改架構的情況下添加新的優化特性,這為面向未來優化 JavaScript 語言特性提供了很好的架構支持,能讓團隊花費更少的時間在做處理不同平臺的特性和編碼上。從原文的數據對比中就可以看到,僅僅是換了個編譯器優化就在 8 倍左右了…… 給 V8 的大佬們跪下了。

而 Orinoco 新的 GC 引擎則是使用多帶帶線程異步去處理,讓其不影響 JS 主線程的執行。至于最后說的 async/await 的 BUG 則是讓 V8 團隊引發思考,將 async/await 原本基于 3 個 Promise 的實現減少成 2 個,最終減少成 1 個!最后達到了寫 async/await 比直接寫 Promise 還要快的結果。

我們知道 await 后面跟的是 Promise 對象,但是即使不是 Promise JS 也會幫我們將其包裝成 Promise。而在 V8 引擎中,為了實現這個包裝,至少需要一個 Promise,兩個微任務過程。這個在本身已經是 Promise 的情況下就有點虧大發了。而為了實現 async/await 在 await 結束之后要重新原函數的上下文并提供 await 之后的結果,規范定義此時還需要一個 Promise,這個在 V8 團隊看來是沒有必要的,所以他們建議規范去除這個特性。

最后的最后,官方還建議我們:多使用 async/await 而不是手寫 Promise 代碼,多使用 JavaScript 引擎提供的 Promise 而不是自己去實現。

Numeric Seperator

隨著 Babel 的出現,JS 的語法糖簡直不要太多,Numeric Seperator 算是一個。簡單的說來它為我們手寫數字的時候提供給了分隔符的支持,讓我們在寫大數字的時候具有可讀性。

其實是個很簡單的語法糖,為什么我會多帶帶列出來說呢,主要是因為它正好解決了我之前一個實現的痛點。我有一個需求是一堆文章數據,我要按照產品給的規則去插入廣告。如圖非紅框是文章,紅框處是廣告。由于插入規則會根據產品的需(心)求(情)頻繁變化,所以我們最開始使用了兩個變量進行標記:

const news = [1, 3, 5, 6, 7, 9, 10, 11];
const ads = [2, 4, 8, 12];

當位置發生變化的時候我們就需要同時對兩個變量進行修改,這樣導致了維護上的成本。所以我想了一個辦法,廣告的位置標記為 1,文章的位置標記為 0,使用純二進制的形式來表示個記錄,這樣子就變成了:

+---+---+---+
| 0 | 1 | 0 |
+---+---+---+
| 1 | 0 | 0 |
+---+---+---+
| 0 | 1 | 0 |
+---+---+---+
| 0 | 0 | 1 |
+---+---+---+

1 011 010 100 010 001
// 首位為常量 1
// 2-4 位記錄一行多少條
// 后續按照新聞和廣告的位置進行記錄

最后我們使用一個變量 0b1011010100010001 就完成了兩種信息的記錄。這樣做將很多數據集成在了一起解決了我們之前的問題,但是它帶來了新的問題,大家也可以看到注釋中按照空格劈開的話大家看的還比較明白,但是在段頭將空格去除之后在閱讀程度上就造成了非常大的困難了。而數字分隔符這個語法糖正好就能解決這個問題,0b1_011_010_100_010_001 這樣閱讀起來就好很多了。

Promise

雖然在大部分的場景 async/await 都可以了,但是不好意思 Promise 有些場景還是不可替代的。Promsie.all()Promise.race() 就是這種特別的存在。而 Promise.allSettled()Promise.any() 則是新增加的方法, 相較于它們的前輩,這倆擁有忽略錯誤達到目的的特性。

我們之前有一個需求,是需要將文件安全的存儲在一個存儲服務中,為了災備我們其實有兩個 S3,一個 HBase 還有本地存儲。所以每次都需要諸如以下的邏輯:

for(const service of services) {
  const result = await service.upload(file);
  if(result) break;
}

但其實我并不關心錯誤,我的目的是只要保證有一個服務最終能執行成功即可,所以 Promise.any() 其實就可以解決這個問題。

await Promise.any( services.map(service => service.upload(file)) );

Promise.allsettled()Promise.any() 的引入豐富了 Promise 更多的可能性。說不定以后還會增加更多的特性,例如 Promise.try(), Promise.some(), Promise.reduce() ...

WeakRef

WeakRef 這個新類型我最開始是不太理解的,畢竟我總感覺 Chrome 已經長大了,肯定會自己處理垃圾了。然而事情并沒有我想的那么簡單,我們知道 JS 的垃圾回收主要有“標記清除”和“引用計數”兩種方法。引用計數是只要變量多一次引用則計數加 1,少一次引用則計數減 1,當引用為 0 時則表示你已經沒有利用價值了,去垃圾站吧!

在 WeakRef 之前其實已經有兩個類似的類型存在了,那就是 WeakMap 和 WeakSet。以 WeakMap 為例,它規定了它的 Key 必須是對象,而且它的對象都是弱引用的。舉個例子:

//map.js
function usageSize() {
  const used = process.memoryUsage().heapUsed;
  return Math.round(used / 1024 / 1024 * 100) / 100 + "M";
}

global.gc();
console.log(usageSize()); // ≈ 3.23M

let arr = new Array(5 * 1024 * 1024);
const map = new Map();

map.set(arr, 1);
global.gc();
console.log(usageSize()); // ≈ 43.22M

arr = null;
global.gc();
console.log(usageSize()); // ≈ 43.23M
//weakmap.js
function usageSize() {
  const used = process.memoryUsage().heapUsed;
  return Math.round(used / 1024 / 1024 * 100) / 100 + "M";
}

global.gc();
console.log(usageSize()); // ≈ 3.23M

let arr = new Array(5 * 1024 * 1024);
const map = new WeakMap();

map.set(arr, 1);
global.gc();
console.log(usageSize()); // ≈ 43.22M

arr = null;
global.gc();
console.log(usageSize()); // ≈ 3.23M

分別執行 node --expose-gc map.jsnode --expose-gc weakmap.js 就可以發現區別了。在 arr 和 Map 中都保留了數組的強引用,所以在 Map 中簡單的清除 arr 變量內存并沒有得到釋放,因為 Map 還存在引用計數。而在 WeakMap 中,它的鍵是弱引用,不計入引用計數中,所以當 arr 被清除之后,數組會因為引用計數為0而被回收掉。

正如分享中所說,WeakMap 和 WeakSet 足夠好,但是它要求鍵必須是對象,在某些場景上不太試用。所以他們暴露了更方便的 WeakRef 類型。在 Python 中也存在 WeakRef 類型,干的事情比較類似。其實我們主要注意 WeakRef 的引用是不計引用計數的,就好理解了。例如 MDN 中所說的引用計數沒辦法清理的循環引用問題:

function f(){
  var o = {};
  var o2 = {};
  o.a = o2; // o 引用 o2
  o2.a = o; // o2 引用 o

  return "azerty";
}

f();

如果試用 WeakRef 來改寫,由于 WeakRef 不計算引用計數,所以計數一直為 0,在下一次回收中就會被正常回收了。

function f() {
  var o = new WeakRef({});
  var o2 = o;
  o.a = o2;

  return "azerty";
}

f();

在之前的一個多進程需求中,我們需要將子進程中的數據發送到主進程中,我們使用的方式是這樣寫的:

const metric = "event";
global.DATA[metric] = {};

process.on(metric, () => {
  const data = global.DATA[metric];
  delete global.DATA[metric];
  return data;
});

代碼就看著比較怪,由于 global.DATA[metric] 作為強引用,如果直接在事件中 return global.DATA[metric] 的話,由于存在引用計數,那么這個全局變量是一直占用內存的。此時如果使用 WeakRef 改寫一下就可以減少 delete 的邏輯了。

const metric = "event";
global.DATA[metric] = new WeakRef({});

process.on(metric, () => {
  const ref = global.DATA[metric];
  if(ref !== undefined) {
    return ref.deref();
  }
  return ref;
});
后記

除了我上面講的幾個特性之外,還有很多其他的特性也非常一顆賽艇。例如 String.matchAll() 讓我們做多次匹配的時候再也不用寫 while 了!Intl 本地化類的支持,讓我們可以早日拋棄 moment.js,特別是 RelativeTimeFormat 類真是解放了我們的生產力,不過目前接口的配置似乎比較定制化,不知道后續的細粒度需求支持情況會如何。

參考資料:

《ES proposal: numeric separators》

《內存管理》

《ES6 系列之 WeakMap》

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

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

相關文章

  • Chrome 63 - What's New in DevTools(中文字幕)

    摘要:一般會每隔周發布一次主版本。于是我就制作了中文字幕并將視頻發到了。站地址中文字幕在開發者博客上,文章也已經在月份發布了,文中提到視頻會在年月底發布,到時候我會繼續制作中文字幕。 大家好,這是代碼之聲(codefm)第一期,今天給大家帶來的是 Whats New In DevTools (Chrome 63)。 Chrome 一般會每隔 6 周發布一次主版本。?目前 Chrome 的最新...

    Shisui 評論0 收藏0
  • Chrome 63 - What's New in DevTools(中文字幕)

    摘要:一般會每隔周發布一次主版本。于是我就制作了中文字幕并將視頻發到了。站地址中文字幕在開發者博客上,文章也已經在月份發布了,文中提到視頻會在年月底發布,到時候我會繼續制作中文字幕。 大家好,這是代碼之聲(codefm)第一期,今天給大家帶來的是 Whats New In DevTools (Chrome 63)。 Chrome 一般會每隔 6 周發布一次主版本。?目前 Chrome 的最新...

    chunquedong 評論0 收藏0
  • 精讀《What's new in javascript》

    摘要:舉例來說即便某個失敗了,也不會導致的發生,這樣在不在乎是否有項目失敗,只要拿到都結束的信號的場景很有用。對于則稍有不同只要有子項,就會完成,哪怕第一個了,而第二個了,也會,而對于,這種場景會直接。 1. 引言 本周精讀的內容是:Google I/O 19。 2019 年 Google I/O 介紹了一些激動人心的 JS 新特性,這些特性有些已經被主流瀏覽器實現,并支持 polyfill...

    dabai 評論0 收藏0
  • [譯]Understanding javascript's 'undefined

    摘要:一個表示編譯器檢測到一個無效的引用值。在實際情況中,往往是在獲取一個未被賦值的引用時被拋出。任何一個函數上下文都有一個被稱為活動對象的變量對象。沒有找到的話,就會認為引用名沒有基礎值并拋出的錯誤。下沒有下的屬性僅存在于被啟動的情況下。 和其他語言相比,javascript中的對于undefined的理解還是有點讓人困惑的。特別是試著理解ReferenceErrors錯誤(x is no...

    galaxy_robot 評論0 收藏0
  • what's the deference between apply bind call?

    摘要:彈出的就是,歲。值得注意的是,和都是改變上下文中的并立即執行這個函數,方法改變了指向之后會返回一個函數,可以隨時調用。和作用完全一樣,只是傳參的方式不一樣。以上,有錯希望各位大神斧正。 apply bind call這三個方法,作用都是改變當前使用該方法的對象的this指向。但三個方法還是有一些區別,先說說共同點。 window.person = { name: mice...

    yintaolaowanzi 評論0 收藏0

發表評論

0條評論

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