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

資訊專欄INFORMATION COLUMN

JavaScript 的未來:它還少些什么?

layman / 2593人閱讀

摘要:例如通過哈希表映射需要一個(gè)操作來檢查值是否相等,另一個(gè)操作用于創(chuàng)建哈希碼。如果使用哈希碼,則對(duì)象應(yīng)該是不可變的。模式匹配提案目前處于第階段。在本文,我們研究其中的智能管道另一個(gè)提議被稱為。更強(qiáng)大,更重量級(jí),并附帶自己的數(shù)據(jù)結(jié)構(gòu)。

翻譯:瘋狂的技術(shù)宅
原文:http://2ality.com/2019/01/fut...

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

近年來,JavaScript 的功能得到了大幅度的增加,本文探討了其仍然缺失的東西。

說明:

我只列出了我所發(fā)現(xiàn)的最重要的功能缺失。當(dāng)然還有很多其它有用的功能,但同時(shí)也會(huì)增加太多的風(fēng)險(xiǎn)。

我的選擇是主觀的。

本文中提及的幾乎所有內(nèi)容都在 TC39 的技術(shù)雷達(dá)上。 也就是說,它還可以作為未來可能的 JavaScript 的預(yù)覽。

有關(guān)前兩個(gè)問題的更多想法,請(qǐng)參閱本文第8節(jié):語言設(shè)計(jì)部分。

1. 值 1.1 按值比較對(duì)象

目前,JavaScript 只能對(duì)原始值(value)進(jìn)行比較,例如字符串的值(通過查看其內(nèi)容):

> "abc" === "abc"
true

相反,對(duì)象則通過身份ID(identity)進(jìn)行比較(對(duì)象僅嚴(yán)格等于自身):

> {x: 1, y: 4} === {x: 1, y: 4}
false

如果有一種能夠創(chuàng)建按值進(jìn)行比較對(duì)象的方法,那將是很不錯(cuò)的:

> #{x: 1, y: 4} === #{x: 1, y: 4}
true

另一種可能性是引入一種新的類(確切的細(xì)節(jié)還有待確定):

@[ValueType]
class Point {
  // ···
}

旁注:這種類似裝飾器的將類標(biāo)記為值類型的的語法基于草案提案。

1.2 將對(duì)象放入數(shù)據(jù)結(jié)構(gòu)中

如果對(duì)象通過身份ID進(jìn)行比較,將它們放入 ECMAScript 數(shù)據(jù)結(jié)構(gòu)(如Maps)中并沒有太大意義:

const m = new Map();
m.set({x: 1, y: 4}, 1);
m.set({x: 1, y: 4}, 2);
assert.equal(m.size, 2);

可以通過自定義值類型修復(fù)此問題。 或者通過自定義 Set 元素和 Map keys 的管理。 例如:

通過哈希表映射:需要一個(gè)操作來檢查值是否相等,另一個(gè)操作用于創(chuàng)建哈希碼。 如果使用哈希碼,則對(duì)象應(yīng)該是不可變的。 否則破壞數(shù)據(jù)結(jié)構(gòu)就太容易了。

通過排序樹映射:需要一個(gè)比較值的操作用來管理它存儲(chǔ)的值。

1.3 大整數(shù)

JavaScript 的數(shù)字總是64位的(雙精度),它能為整數(shù)提供53位二進(jìn)制寬度。這意味著如果超過53位,就不好使了:

> 2 ** 53
9007199254740992
> (2 ** 53) + 1  // can’t be represented
9007199254740992
> (2 ** 53) + 2
9007199254740994

對(duì)于某些場景,這是一個(gè)相當(dāng)大的限制?,F(xiàn)在有[BigInts提案](http://2ality.com/2017/03/es-...),這是真正的整數(shù),其精度可以隨著需要而增長:

> 2n ** 53n
9007199254740992n
> (2n ** 53n) + 1n
9007199254740993n

BigInts還支持 casting,它為你提供固定位數(shù)的值:

const int64a = BigInt.asUintN(64, 12345n);
const int64b = BigInt.asUintN(64, 67890n);
const result = BigInt.asUintN(64, int64a * int64b);
1.4 小數(shù)計(jì)算

JavaScript 的數(shù)字是基于 IEEE 754 標(biāo)準(zhǔn)的64位浮點(diǎn)數(shù)(雙精度數(shù))。鑒于它們的表示形式是基于二進(jìn)制的,在處理小數(shù)部分時(shí)可能會(huì)出現(xiàn)舍入誤差:

> 0.1 + 0.2
0.30000000000000004

這在科學(xué)計(jì)算和金融技術(shù)(金融科技)中尤其成問題?;谑M(jìn)制運(yùn)算的提案目前處于階段0。它們可能最終被這樣使用(注意十進(jìn)制數(shù)的后綴 m):

> 0.1m + 0.2m
0.3m
1.5 對(duì)值進(jìn)行分類

目前,在 JavaScript 中對(duì)值進(jìn)行分類非常麻煩:

首先,你必須決定是否使用 typeofinstanceof。

其次,typeof 有一個(gè)眾所周知的的怪癖,就是把 null 歸類為“對(duì)象”。我還認(rèn)為函數(shù)被歸類為 "function" 同樣是奇怪的。

> typeof null
"object"
> typeof function () {}
"function"
> typeof []
"object"

第三,instanceof 不適用于來自其他realm(框架等)的對(duì)象。

也許可能通過庫來解決這個(gè)問題(如果我有時(shí)間,就會(huì)實(shí)現(xiàn)一個(gè)概念性的驗(yàn)證)。

2. 函數(shù)式編程 2.1 更多表達(dá)式

不幸的是C風(fēng)格的語言在表達(dá)式和語句之間做出了區(qū)分:

// 條件表達(dá)式
let str1 = someBool ? "yes" : "no";

// 條件聲明
let str2;
if (someBool) {
  str2 = "yes";
} else {
  str2 = "no";
}

特別是在函數(shù)式語言中,一切都是表達(dá)式。 Do-expressions 允許你在所有表達(dá)式上下文中使用語句:

let str3 = do {
  if (someBool) {
    "yes"
  } else {
    "no"
  }
};

下面的代碼是一個(gè)更加現(xiàn)實(shí)的例子。如果沒有 do-expression,你需要一個(gè)立即調(diào)用的箭頭函數(shù)來隱藏范圍內(nèi)的變量 result

const func = (() => {
  let result; // cache
  return () => {
    if (result === undefined) {
      result = someComputation();
    }
    return result;
  }
})();

使用 do-expression,你可以更優(yōu)雅地編寫這段代碼:

const func = do {
  let result;
  () => {
    if (result === undefined) {
      result = someComputation();
    }
    return result;
  };
};
2.2 匹配:解構(gòu) switch

JavaScript 使直接使用對(duì)象變得容易。但是根據(jù)對(duì)象的結(jié)構(gòu),沒有內(nèi)置的切換 case 分支的方法??雌饋硎沁@樣的(來自提案的例子):

const resource = await fetch(jsonService);
case (resource) {
  when {status: 200, headers: {"Content-Length": s}} -> {
    console.log(`size is ${s}`);
  }
  when {status: 404} -> {
    console.log("JSON not found");
  }
  when {status} if (status >= 400) -> {
    throw new RequestError(res);
  }
}

正如你所看到的那樣,新的 case 語句在某些方面類似于 switch,不過它使用解構(gòu)來挑選分支。當(dāng)人們使用嵌套數(shù)據(jù)結(jié)構(gòu)(例如在編譯器中)時(shí),這種功能非常有用。 模式匹配提案目前處于第1階段。

2.3 管道操作

管道操作目前有兩個(gè)競爭提案 。在本文,我們研究其中的 智能管道(另一個(gè)提議被稱為 F# Pipelines)。

管道操作的基本思想如下。請(qǐng)考慮代碼中的嵌套函數(shù)調(diào)用。

const y = h(g(f(x)));

但是,這種表示方法通常不能體現(xiàn)我們對(duì)計(jì)算步驟的看法。在直覺上,我們將它們描述為:

從值 x 開始。

然后把 f() 作用在 x 上。

然后將 g() 作用于結(jié)果。

然后將 h() 應(yīng)用于結(jié)果。

最后將結(jié)果賦值給 y。

管道運(yùn)算符能讓我們更好地表達(dá)這種直覺:

const y = x |> f |> g |> h;

換句話說,以下兩個(gè)表達(dá)式是等價(jià)的。

f(123)
123 |> f

另外,管道運(yùn)算符支持部分應(yīng)用程序(類似函數(shù)的 .bind() 方法):以下兩個(gè)表達(dá)式是等價(jià)的。

123 |> f(#)
123 |> (x => f(x))

使用管道運(yùn)算符一個(gè)最大的好處是,你可以像使用方法一樣使用函數(shù)——而無需更改任何原型:

import {map} from "array-tools";
const result = arr |> map(#, x => x * 2);

最后,讓我們看一個(gè)長一點(diǎn)的例子(取自提案并稍作編輯):

promise
|> await #
|> # || throw new TypeError(
  `Invalid value from ${promise}`)
|> capitalize // function call
|> # + "!"
|> new User.Message(#)
|> await stream.write(#)
|> console.log // method call
;
3 并發(fā)

一直以來 JavaScript 對(duì)并發(fā)性的支持很有限。并發(fā)進(jìn)程的事實(shí)標(biāo)準(zhǔn)是 Worker API,可以在 web browsers 和 Node.js (在 v11.7 及更高版本中沒有標(biāo)記)中找到。

在Node.js中的使用方法它如下所示:

const {
  Worker, isMainThread, parentPort, workerData
} = require("worker_threads");

if (isMainThread) {
  const worker = new Worker(__filename, {
    workerData: "the-data.json"
  });
  worker.on("message", result => console.log(result));
  worker.on("error", err => console.error(err));
  worker.on("exit", code => {
    if (code !== 0) {
      console.error("ERROR: " + code);
    }
  });
} else {
  const {readFileSync} = require("fs");
  const fileName = workerData;
  const text = readFileSync(fileName, {encoding: "utf8"});
  const json = JSON.parse(text);
  parentPort.postMessage(json);
}

唉,相對(duì)來說 Workers 是重量級(jí)的 —— 每個(gè)都有自己的 realm(全局變量等)。我想在未來看到一個(gè)更加輕量級(jí)的構(gòu)造。

4. 標(biāo)準(zhǔn)庫

JavaScript 仍然明顯落后于其他語言的一個(gè)領(lǐng)域是它的標(biāo)準(zhǔn)庫。當(dāng)然保持最小化是有意義的,因?yàn)橥獠繋旄菀走M(jìn)化和適應(yīng)。但是有一些核心功能也是有必要的。

4.1 用模塊替代命名空間對(duì)象

JavaScript 標(biāo)準(zhǔn)庫是在其語言具有模塊之前創(chuàng)建的。因此函數(shù)被放在命名空間對(duì)象中,例如ObjectReflect,MathJSON

Object.keys()

Reflect.ownKeys()

Math.sign()

JSON.parse()

如果將這個(gè)功能放在模塊中會(huì)更好。它必須通過特殊的URL訪問,例如使用偽協(xié)議 std

// Old:
assert.deepEqual(
  Object.keys({a: 1, b: 2}),
  ["a", "b"]);

// New:
import {keys} from "std:object";
assert.deepEqual(
  keys({a: 1, b: 2}),
  ["a", "b"]);

好處是:

JavaScript 將變得更加模塊化(這可以加快啟動(dòng)時(shí)間并減少內(nèi)存消耗)。

調(diào)用導(dǎo)入的函數(shù)比調(diào)用存儲(chǔ)在對(duì)象中的函數(shù)更快。

4.2 可迭代工具 (sync 與 async)

迭代 的好處包括按需計(jì)算和支持許多數(shù)據(jù)源。但是目前 JavaScript 只提供了很少的工具來處理 iterables。例如,如果要 過濾、映射或消除重復(fù),則必須將其轉(zhuǎn)換為數(shù)組:

const iterable = new Set([-1, 0, -2, 3]);
const filteredArray = [...iterable].filter(x => x >= 0);
assert.deepEqual(filteredArray, [0, 3]);

如果 JavaScript 具有可迭代的工具函數(shù),你可以直接過濾迭代:

const filteredIterable = filter(iterable, x => x >= 0);
assert.deepEqual(
  // We only convert the iterable to an Array, so we can
  // check what’s in it:
  [...filteredIterable], [0, 3]);

以下是迭代工具函數(shù)的一些示例:

// Count elements in an iterable
assert.equal(count(iterable), 4);

// Create an iterable over a part of an existing iterable
assert.deepEqual(
  [...slice(iterable, 2)],
  [-1, 0]);

// Number the elements of an iterable
// (producing another – possibly infinite – iterable)
for (const [i,x] of zip(range(0), iterable)) {
  console.log(i, x);
}
// Output:
// 0, -1
// 1, 0
// 2, -2
// 3, 3

筆記:

有關(guān)迭代器的工具函數(shù)示例,請(qǐng)參閱 Python 的 itertools (https://docs.python.org/3/lib...)。

對(duì)于 JavaScript,迭代的每個(gè)工具函數(shù)應(yīng)該有兩個(gè)版本:一個(gè)用于同步迭代,一個(gè)用于異步迭代。

4.3 不可變數(shù)據(jù)

很高興能看到對(duì)數(shù)據(jù)的非破壞性轉(zhuǎn)換有更多的支持。兩個(gè)相關(guān)的庫是:

Immer 相對(duì)輕量,適用于普通對(duì)象和數(shù)組。

Immutable.js 更強(qiáng)大,更重量級(jí),并附帶自己的數(shù)據(jù)結(jié)構(gòu)。

4.4 更好地支持日期和時(shí)間

JavaScript 對(duì)日期和時(shí)間的內(nèi)置支持有許多奇怪的地方。這就是為什么目前建議用庫來完成除了最基本任務(wù)之外的其它所有工作。

值得慶幸的是 temporal 是一個(gè)更好的時(shí)間 API:

const dateTime = new CivilDateTime(2000, 12, 31, 23, 59);
const instantInChicago = dateTime.withZone("America/Chicago");
5. 可能不需要的功能 5.1 optional chaining 的優(yōu)缺點(diǎn)

一個(gè)相對(duì)流行的提議功能是 optional chaining。以下兩個(gè)表達(dá)式是等效的。

obj?.prop
(obj === undefined || obj === null) ? undefined : obj.prop

此功能對(duì)于屬性鏈特別方便:

obj?.foo?.bar?.baz

但是,仍然存在缺點(diǎn):

深層嵌套的結(jié)構(gòu)更難管理。

由于在訪問數(shù)據(jù)時(shí)過于寬容,隱藏了以后可能會(huì)出現(xiàn)的問題,更難以調(diào)試。

optional chaining 的替代方法是在單個(gè)位置提取一次信息:

你可以編寫一個(gè)提取數(shù)據(jù)的輔助函數(shù)。

或者你可以編寫一個(gè)函數(shù),使其輸入是深層嵌套數(shù)據(jù),但是輸出更簡單、標(biāo)準(zhǔn)化的數(shù)據(jù)。

無論采用哪種方法,都可以執(zhí)行檢查并在出現(xiàn)問題時(shí)盡早拋出異常。

進(jìn)一步閱讀:

“Overly defensive programming” by Carl Vitullo

Thread on Twitter by Cory House

5.2 我們需要運(yùn)算符重載嗎?

目前正在為 運(yùn)算符重載 進(jìn)行早期工作,但是 infix 函數(shù)可能就足夠了(目前還沒有提案):

import {BigDecimal, plus} from "big-decimal";
const bd1 = new BigDecimal("0.1");
const bd2 = new BigDecimal("0.2");
const bd3 = bd1 @plus bd2; // plus(bd1, bd2)

infix 函數(shù)的好處是:

你可以創(chuàng)建 JavaScript 以外的運(yùn)算符。

與普通函數(shù)相比,嵌套表達(dá)式的可讀性仍然很好。

下面是嵌套表達(dá)式的例子:

a @plus b @minus c @times d
times(minus(plus(a, b), c), d)

有趣的是,管道操作符還有助于提高可讀性:

plus(a, b)
  |> minus(#, c)
  |> times(#, d)
6. 各種小東西

以下是我偶爾會(huì)遺漏的一些東西,但我認(rèn)為不如前面提到的那些重要:

鏈?zhǔn)疆惓#菏鼓隳軌虿东@錯(cuò)誤,能夠包含其他信息并再次拋出。

  new ChainedError(msg, origError)

可組合的正則表達(dá)式:

  re`/^${RE_YEAR}-${RE_MONTH}-${RE_DAY}$/u`

正則表達(dá)式的轉(zhuǎn)義文本(對(duì)于.replace()很重要):

> const re = new RegExp(RegExp.escape(":-)"), "ug");
> ":-) :-) :-)".replace(re, "           
               
                                           
                       
                 

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

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

相關(guān)文章

  • ES6-箭頭函數(shù)

    摘要:編程中經(jīng)常定義一些短小的匿名函數(shù),使用箭頭函數(shù)語法可使得這類函數(shù)的定義更加簡潔。外部函數(shù)的,等價(jià)于定義個(gè)局部變量修改內(nèi)部的所以這樣,,也就無法修改箭頭函數(shù)的值的。拋異常即箭頭函數(shù)不能作為構(gòu)造函數(shù),其也不具有屬性。 一、概述 箭頭函數(shù)是指通過=>語法定義的函數(shù)。JS編程中經(jīng)常定義一些短小的匿名函數(shù),使用箭頭函數(shù)語法可使得這類函數(shù)的定義更加簡潔。 // ES3/5方式 var fun1 =...

    wapeyang 評(píng)論0 收藏0
  • 7個(gè) HTML 面試題及回答策略

    摘要:接下來,我會(huì)檢查每個(gè)頁面以確保它使用有用的標(biāo)簽,包括標(biāo)題標(biāo)簽。這個(gè)問題讓面試官有機(jī)會(huì)了解潛在員工對(duì)工作難以勝任的部分。面試官可能需要考慮這種弱點(diǎn)對(duì)團(tuán)隊(duì)的影響。面試官可能會(huì)發(fā)現(xiàn)自己公司的計(jì)劃與未來員工的職業(yè)目標(biāo)是否保持一致。 翻譯:瘋狂的技術(shù)宅原文:https://www.indeed.com/hire/i... 本文首發(fā)微信公眾號(hào):jingchengyideng歡迎關(guān)注,每天都給你...

    Luosunce 評(píng)論0 收藏0
  • 2018年前端開發(fā)回顧

    摘要:在整個(gè)年,看到發(fā)布版增加了許多功能,包括新的生命周期方法新的上下文指針事件延遲函數(shù)和。它在等待渲染異步響應(yīng)時(shí)數(shù)據(jù),是延遲函數(shù)背后用來管理組件的代碼分割的。發(fā)布自第版開始將近年后,于年發(fā)布。 前端發(fā)展發(fā)展迅速,非常的快。 本文將回顧2018年一些重要的前端新聞,事件和 JavaScript 趨勢。 想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你! showImg(ht...

    crelaber 評(píng)論0 收藏0
  • WebAssembly 為什么比 asm.js 快?

    摘要:并且于年月日,四個(gè)主要的瀏覽器一致同意宣布的版本已經(jīng)完成,即將推出一個(gè)瀏覽器可以搭載的穩(wěn)定版本。因此本文著重介紹為什么比更快。本文主要表達(dá)的是為什么應(yīng)該是更快的。則不同,它是由幾大主要的瀏覽器廠商共同設(shè)計(jì)的。 作者:Alon Zakai 編譯:胡子大哈 翻譯原文:http://huziketang.com/blog/posts/detail?postId=58ce80d2a6d8a0...

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

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

0條評(píng)論

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