真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

javascript提案的簡單介紹

js精度計(jì)算

在新公司的第一個(gè)項(xiàng)目是區(qū)塊鏈相關(guān)的管理后臺(tái)和交易所,其中就涉及了很多的計(jì)算問題。而JavaScript因?yàn)榇嬖谟?jì)算的精度問題,所以直接計(jì)算就可能會(huì)導(dǎo)致各種各樣的bug,為了解決這個(gè)問題,就要使用BigNumber.js這個(gè)庫。

成都創(chuàng)新互聯(lián)公司是一家集網(wǎng)站建設(shè),思明企業(yè)網(wǎng)站建設(shè),思明品牌網(wǎng)站建設(shè),網(wǎng)站定制,思明網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,思明網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

至于為什么JavaScript會(huì)有精度問題呢,可以看 這里 。簡單來說就是因?yàn)椋?JavaScript中所有的數(shù)字(包括整數(shù)和小數(shù))都只有一種類型–Number。它的實(shí)現(xiàn)遵循IEEE 754標(biāo)準(zhǔn),使用64位固定長度來表示,也就是標(biāo)準(zhǔn)的double雙精度浮點(diǎn)數(shù)。它的優(yōu)點(diǎn)是可以歸一化處理整數(shù)和小數(shù),節(jié)省儲(chǔ)存空間。而實(shí)際計(jì)算的時(shí)候會(huì)轉(zhuǎn)換成二進(jìn)制計(jì)算再轉(zhuǎn)成十進(jìn)制。進(jìn)制轉(zhuǎn)換之后會(huì)很長,舍去一部分,計(jì)算再轉(zhuǎn)回來,就有了精度誤差。

BigNumber.js是一個(gè)用于任意精度計(jì)算的js庫。可以在? 官方文檔 ?的console中測試使用。也可以通過npm install bignumber.js --save來安裝。然后?import BigNumber from 'bignumber.js'?來引入使用。他的大概原理是將所有數(shù)字當(dāng)做字符串,重新實(shí)現(xiàn)了計(jì)算邏輯。缺點(diǎn)是性能比原生的差很多。

現(xiàn)在 TC39 已經(jīng)有一個(gè) Stage 3 的提案 proposal bigint,大數(shù)問題有望徹底解決。在瀏覽器正式支持前,可以使用 Babel 7.0 來實(shí)現(xiàn),它的內(nèi)部是自動(dòng)轉(zhuǎn)換成 big-integer 來計(jì)算,要注意的是這樣能保持精度但運(yùn)算效率會(huì)降低。

具體用法可以參考以下資料:

官方文檔

bignumber.js使用記錄

BigNumber 講解

就不再敖述了,下邊隨便寫點(diǎn)常用的方法:

// 轉(zhuǎn)為 bignumberconstx=newBigNumber('123456789.123456789');// 轉(zhuǎn)為 普通數(shù)字x.toNumber()// 格式化(小數(shù)點(diǎn))x.toFormat()// '123,456,789.123456789'x.toFormat(3)// '123,456,789.123'// 計(jì)算x.plus(0.1)// 加法x.minus(0.1)// 減法x.times(0.1)// 乘法x.div(0.1)// 除法x.mod(3)// 取模/取余// 比較大小x.eq(y)// isEqualTo 的簡寫,是否相等x.gt(y)// isGreaterThan 的簡寫,是否大于x.gte(y)// isGreaterThanOrEqualTo 的簡寫,是否大于等于x.lt(y)// isLessThan 的簡寫,是否小于x.lte(y)// isLessThanOrEqualTo 的簡寫,是否小于等于// 取非,改變數(shù)字的正負(fù)號(hào)x.negated()

【Flutter】利用Future封裝出js中的Promise

前端的同學(xué)對(duì) Promise 肯定都很熟悉,而 Future 便是 dart 中 Promise ,但方法名稱和使用方式還是有些許的差異的。

下面我們嘗試,利用 Future 封裝出js中我們熟悉的 Promise 。

使用示例

Promise.all , Promise.race , Promise.resolve , Promise.reject

Promise.allSettled 方法接受一組 Promise 實(shí)例作為參數(shù),包裝成一個(gè)新的 Promise 實(shí)例。只有等到所有這些參數(shù)實(shí)例都返回結(jié)果,不管是 fulfilled 還是 rejected ,包裝實(shí)例才會(huì)結(jié)束。該方法由 ES2020 引入

Promise.any() 方法接受一組 Promise 實(shí)例作為參數(shù),包裝成一個(gè)新的 Promise 實(shí)例。只要參數(shù)實(shí)例有一個(gè)變成 fulfilled 狀態(tài),包裝實(shí)例就會(huì)變成 fulfilled 狀態(tài);如果所有參數(shù)實(shí)例都變成 rejected 狀態(tài),包裝實(shí)例就會(huì)變成 rejected 狀態(tài)。該方法目前是一個(gè)第三階段的 提案 。

Promise.any() 跟 Promise.race() 方法很像,只有一點(diǎn)不同,就是不會(huì)因?yàn)槟硞€(gè) Promise 變成 rejected 狀態(tài)而結(jié)束。

順便把 延遲函數(shù) 也封裝一下,畢竟毫秒延遲的使用頻率是最高的。

javascript中異步操作的異常怎么處理

一、JavaScript異步編程的兩個(gè)核心難點(diǎn)

異步I/O、事件驅(qū)動(dòng)使得單線程的JavaScript得以在不阻塞UI的情況下執(zhí)行網(wǎng)絡(luò)、文件訪問功能,且使之在后端實(shí)現(xiàn)了較高的性能。然而異步風(fēng)格也引來了一些麻煩,其中比較核心的問題是:

1、函數(shù)嵌套過深

JavaScript的異步調(diào)用基于回調(diào)函數(shù),當(dāng)多個(gè)異步事務(wù)多級(jí)依賴時(shí),回調(diào)函數(shù)會(huì)形成多級(jí)的嵌套,代碼變成

金字塔型結(jié)構(gòu)。這不僅使得代碼變難看難懂,更使得調(diào)試、重構(gòu)的過程充滿風(fēng)險(xiǎn)。

2、異常處理

回調(diào)嵌套不僅僅是使代碼變得雜亂,也使得錯(cuò)誤處理更復(fù)雜。這里主要講講異常處理。

二、異常處理

像很多時(shí)髦的語言一樣,JavaScript 也允許拋出異常,隨后再用一個(gè)try/catch

語句塊捕獲。如果拋出的異常未被捕獲,大多數(shù)JavaScript環(huán)境都會(huì)提供一個(gè)有用的堆棧軌跡。舉個(gè)例子,下面這段代碼由于'{'為無效JSON

對(duì)象而拋出異常。

?

12345678

function JSONToObject(jsonStr) { return JSON.parse(jsonStr);}var obj = JSONToObject('{');//SyntaxError: Unexpected end of input//at Object.parse (native)//at JSONToObject (/AsyncJS/stackTrace.js:2:15)//at Object.anonymous (/AsyncJS/stackTrace.js:4:11)

堆棧軌跡不僅告訴我們哪里拋出了錯(cuò)誤,而且說明了最初出錯(cuò)的地方:第4 行代碼。遺憾的是,自頂向下地跟蹤異步錯(cuò)誤起源并不都這么直截了當(dāng)。

異步編程中可能拋出錯(cuò)誤的情況有兩種:回調(diào)函數(shù)錯(cuò)誤、異步函數(shù)錯(cuò)誤。

1、回調(diào)函數(shù)錯(cuò)誤

如果從異步回調(diào)中拋出錯(cuò)誤,會(huì)發(fā)生什么事?讓我們先來做個(gè)測試。

?

1234567

setTimeout(function A() { setTimeout(function B() { setTimeout(function C() { throw new Error('Something terrible has happened!'); }, 0); }, 0);}, 0);

上述應(yīng)用的結(jié)果是一條極其簡短的堆棧軌跡。

?

12

Error: Something terrible has happened!at Timer.C (/AsyncJS/nestedErrors.js:4:13)

等等,A 和B 發(fā)生了什么事?為什么它們沒有出現(xiàn)在堆棧軌跡中?這是因?yàn)檫\(yùn)行C 的時(shí)候,異步函數(shù)的上下文已經(jīng)不存在了,A 和B 并不在內(nèi)存堆棧里。這3

個(gè)函數(shù)都是從事件隊(duì)列直接運(yùn)行的?;谕瑯拥睦碛?,利用try/catch

語句塊并不能捕獲從異步回調(diào)中拋出的錯(cuò)誤。另外回調(diào)函數(shù)中的return也失去了意義。

?

1234567

try { setTimeout(function() { throw new Error('Catch me if you can!'); }, 0);} catch (e) {console.error(e);}

看到這里的問題了嗎?這里的try/catch 語句塊只捕獲setTimeout函數(shù)自身內(nèi)部發(fā)生的那些錯(cuò)誤。因?yàn)閟etTimeout

異步地運(yùn)行其回調(diào),所以即使延時(shí)設(shè)置為0,回調(diào)拋出的錯(cuò)誤也會(huì)直接流向應(yīng)用程序。

總的來說,取用異步回調(diào)的函數(shù)即使包裝上try/catch 語句塊,也只是無用之舉。(特例是,該異步函數(shù)確實(shí)是在同步地做某些事且容易出錯(cuò)。例如,Node

的fs.watch(file,callback)就是這樣一個(gè)函數(shù),它在目標(biāo)文件不存在時(shí)會(huì)拋出一個(gè)錯(cuò)誤。)正因?yàn)榇耍琋ode.js

中的回調(diào)幾乎總是接受一個(gè)錯(cuò)誤作為其首個(gè)參數(shù),這樣就允許回調(diào)自己來決定如何處理這個(gè)錯(cuò)誤。

2、異步函數(shù)錯(cuò)誤

由于異步函數(shù)是立刻返回的,異步事務(wù)中發(fā)生的錯(cuò)誤是無法通過try-catch來捕捉的,只能采用由調(diào)用方提供錯(cuò)誤處理回調(diào)的方案來解決。

例如Node中常見的function (err, ...)

{...}回調(diào)函數(shù),就是Node中處理錯(cuò)誤的約定:即將錯(cuò)誤作為回調(diào)函數(shù)的第一個(gè)實(shí)參返回。再比如HTML5中FileReader對(duì)象的onerror函數(shù),會(huì)被用于處理異步讀取文件過程中的錯(cuò)誤。

舉個(gè)例子,下面這個(gè)Node 應(yīng)用嘗試異步地讀取一個(gè)文件,還負(fù)責(zé)記錄下任何錯(cuò)誤(如“文件不存在”)。

?

1234567

var fs = require('fs'); fs.readFile('fhgwgdz.txt', function(err, data) { if (err) { return console.error(err); }; console.log(data.toString('utf8'));});

客戶端JavaScript 庫的一致性要稍微差些,不過最常見的模式是,針對(duì)成敗這兩種情形各規(guī)定一個(gè)單獨(dú)的回調(diào)。jQuery 的Ajax

方法就遵循了這個(gè)模式。

?

1234

$.get('/data', { success: successHandler, failure: failureHandler});

不管API 形態(tài)像什么,始終要記住的是,只能在回調(diào)內(nèi)部處理源于回調(diào)的異步錯(cuò)誤。

三、未捕獲異常的處理

如果是從回調(diào)中拋出異常的,則由那個(gè)調(diào)用了回調(diào)的人負(fù)責(zé)捕獲該異常。但如果異常從未被捕獲,又會(huì)怎么樣?這時(shí),不同的JavaScript環(huán)境有著不同的游戲規(guī)則……

1. 在瀏覽器環(huán)境中

現(xiàn)代瀏覽器會(huì)在開發(fā)人員控制臺(tái)顯示那些未捕獲的異常,接著返回事件隊(duì)列。要想修改這種行為,可以給window.onerror

附加一個(gè)處理器。如果windows.onerror 處理器返回true,則能阻止瀏覽器的默認(rèn)錯(cuò)誤處理行為。

?

123

window.onerror = function(err) { return true; //徹底忽略所有錯(cuò)誤};

在成品應(yīng)用中, 會(huì)考慮某種JavaScript 錯(cuò)誤處理服務(wù), 譬如Errorception。Errorception

提供了一個(gè)現(xiàn)成的windows.onerror 處理器,它向應(yīng)用服務(wù)器報(bào)告所有未捕獲的異常,接著應(yīng)用服務(wù)器發(fā)送消息通知我們。

2. 在Node.js 環(huán)境中

在Node 環(huán)境中,window.onerror 的類似物就是process 對(duì)象的uncaughtException 事件。正常情況下,Node

應(yīng)用會(huì)因未捕獲的異常而立即退出。但只要至少還有一個(gè)uncaughtException 事件處理

器,Node 應(yīng)用就會(huì)直接返回事件隊(duì)列。

?

123

process.on('uncaughtException', function(err) { console.error(err); //避免了關(guān)停的命運(yùn)!});

但是,自Node 0.8.4 起,uncaughtException 事件就被廢棄了。據(jù)其文檔所言,對(duì)異常處理而言,uncaughtException

是一種非常粗暴的機(jī)制,請(qǐng)勿使用uncaughtException,而應(yīng)使用Domain 對(duì)象。

Domain 對(duì)象又是什么?你可能會(huì)這樣問。Domain 對(duì)象是事件化對(duì)象,它將throw 轉(zhuǎn)化為'error'事件。下面是一個(gè)例子。

?

123456789

var myDomain = require('domain').create();myDomain.run(function() { setTimeout(function() { throw new Error('Listen to me!') }, 50);});myDomain.on('error', function(err) { console.log('Error ignored!');});

源于延時(shí)事件的throw 只是簡單地觸發(fā)了Domain 對(duì)象的錯(cuò)誤處理器。

Error ignored!

很奇妙,是不是?Domain 對(duì)象讓throw

語句生動(dòng)了很多。不管在瀏覽器端還是服務(wù)器端,全局的異常處理器都應(yīng)被視作最后一根救命稻草。請(qǐng)僅在調(diào)試時(shí)才使用它。

四、幾種解決方案

下面對(duì)幾種解決方案的討論主要集中于上面提到的兩個(gè)核心問題上,當(dāng)然也會(huì)考慮其他方面的因素來評(píng)判其優(yōu)缺點(diǎn)。

1、Async.js

首先是Node中非常著名的Async.js,這個(gè)庫能夠在Node中展露頭角,恐怕也得歸功于Node統(tǒng)一的錯(cuò)誤處理約定。

而在前端,一開始并沒有形成這么統(tǒng)一的約定,因此使用Async.js的話可能需要對(duì)現(xiàn)有的庫進(jìn)行封裝。

Async.js的其實(shí)就是給回調(diào)函數(shù)的幾種常見使用模式加了一層包裝。比如我們需要三個(gè)前后依賴的異步操作,采用純回調(diào)函數(shù)寫法如下:

?

12345678910111213141516

asyncOpA(a, b, (err, result) = { if (err) { handleErrorA(err); } asyncOpB(c, result, (err, result) = { if (err) { handleErrorB(err); } asyncOpB(d, result, (err, result) = { if (err) { handlerErrorC(err); } finalOp(result); }); });});

如果我們采用async庫來做:

?

12345678910111213141516171819202122

async.waterfall([ (cb) = { asyncOpA(a, b, (err, result) = { cb(err, c, result); }); }, (c, lastResult, cb) = { asyncOpB(c, lastResult, (err, result) = { cb(err, d, result); }) }, (d, lastResult, cb) = { asyncOpC(d, lastResult, (err, result) = { cb(err, result); }); }], (err, finalResult) = { if (err) { handlerError(err); } finalOp(finalResult);});

可以看到,回調(diào)函數(shù)由原來的橫向發(fā)展轉(zhuǎn)變?yōu)榭v向發(fā)展,同時(shí)錯(cuò)誤被統(tǒng)一傳遞到最后的處理函數(shù)中。

其原理是,將函數(shù)數(shù)組中的后一個(gè)函數(shù)包裝后作為前一個(gè)函數(shù)的末參數(shù)cb傳入,同時(shí)要求:

每一個(gè)函數(shù)都應(yīng)當(dāng)執(zhí)行其cb參數(shù);cb的第一個(gè)參數(shù)用來傳遞錯(cuò)誤。我們可以自己寫一個(gè)async.waterfall的實(shí)現(xiàn):

?

12345678910111213141516171819202122

let async = { waterfall: (methods, finalCb = _emptyFunction) = { if (!_isArray(methods)) { return finalCb(new Error('First argument to waterfall must be an array of functions')); } if (!methods.length) { return finalCb(); } function wrap(n) { if (n === methods.length) { return finalCb; } return function (err, ...args) { if (err) { return finalCb(err); } methods[n](...args, wrap(n + 1)); } } wrap(0)(false); }};

Async.js還有series/parallel/whilst等多種流程控制方法,來實(shí)現(xiàn)常見的異步協(xié)作。

Async.js的問題:

在外在上依然沒有擺脫回調(diào)函數(shù),只是將其從橫向發(fā)展變?yōu)榭v向,還是需要程序員熟練異步回調(diào)風(fēng)格。

錯(cuò)誤處理上仍然沒有利用上try-catch和throw,依賴于“回調(diào)函數(shù)的第一個(gè)參數(shù)用來傳遞錯(cuò)誤”這樣的一個(gè)約定。

2、Promise方案

ES6的Promise來源于Promise/A+。使用Promise來進(jìn)行異步流程控制,有幾個(gè)需要注意的問題,

把前面提到的功能用Promise來實(shí)現(xiàn),需要先包裝異步函數(shù),使之能返回一個(gè)Promise:

?

12345678910

function toPromiseStyle(fn) { return (...args) = { return new Promise((resolve, reject) = { fn(...args, (err, result) = { if (err) reject(err); resolve(result); }) }); };}

這個(gè)函數(shù)可以把符合下述規(guī)則的異步函數(shù)轉(zhuǎn)換為返回Promise的函數(shù):

回調(diào)函數(shù)的第一個(gè)參數(shù)用于傳遞錯(cuò)誤,第二個(gè)參數(shù)用于傳遞正常的結(jié)果。接著就可以進(jìn)行操作了:

?

123456789101112131415

let [opA, opB, opC] = [asyncOpA, asyncOpB, asyncOpC].map((fn) = toPromiseStyle(fn)); opA(a, b) .then((res) = { return opB(c, res); }) .then((res) = { return opC(d, res); }) .then((res) = { return finalOp(res); }) .catch((err) = { handleError(err); });

通過Promise,原來明顯的異步回調(diào)函數(shù)風(fēng)格顯得更像同步編程風(fēng)格,我們只需要使用then方法將結(jié)果傳遞下去即可,同時(shí)return也有了相應(yīng)的意義:

在每一個(gè)then的onFullfilled函數(shù)(以及onRejected)里的return,都會(huì)為下一個(gè)then的onFullfilled函數(shù)(以及onRejected)的參數(shù)設(shè)定好值。

如此一來,return、try-catch/throw都可以使用了,但catch是以方法的形式出現(xiàn),還是不盡如人意。

3、Generator方案

ES6引入的Generator可以理解為可在運(yùn)行中轉(zhuǎn)移控制權(quán)給其他代碼,并在需要的時(shí)候返回繼續(xù)執(zhí)行的函數(shù)。利用Generator可以實(shí)現(xiàn)協(xié)程的功能。

將Generator與Promise結(jié)合,可以進(jìn)一步將異步代碼轉(zhuǎn)化為同步風(fēng)格:

?

1234567891011

function* getResult() { let res, a, b, c, d; try { res = yield opA(a, b); res = yield opB(c, res); res = yield opC(d); return res; } catch (err) { return handleError(err); }}

然而我們還需要一個(gè)可以自動(dòng)運(yùn)行Generator的函數(shù):

?

123456789101112131415161718192021222324252627282930

function spawn(genF, ...args) { return new Promise((resolve, reject) = { let gen = genF(...args); function next(fn) { try { let r = fn(); if (r.done) { resolve(r.value); } Promise.resolve(r.value) .then((v) = { next(() = { return gen.next(v); }); }).catch((err) = { next(() = { return gen.throw(err); }) }); } catch (err) { reject(err); } } next(() = { return gen.next(undefined); }); });}

用這個(gè)函數(shù)來調(diào)用Generator即可:

?

1234567

spawn(getResult) .then((res) = { finalOp(res); }) .catch((err) = { handleFinalOpError(err); });

可見try-catch和return實(shí)際上已經(jīng)以其原本面貌回到了代碼中,在代碼形式上也已經(jīng)看不到異步風(fēng)格的痕跡。

類似的功能有co/task.js等庫實(shí)現(xiàn)。

4、ES7的async/await

ES7中將會(huì)引入async function和await關(guān)鍵字,利用這個(gè)功能,我們可以輕松寫出同步風(fēng)格的代碼,

同時(shí)依然可以利用原有的異步I/O機(jī)制。

采用async function,我們可以將之前的代碼寫成這樣:

?

12345678910111213

async function getResult() { let res, a, b, c, d; try { res = await opA(a, b); res = await opB(c, res); res = await opC(d); return res; } catch (err) { return handleError(err); }} getResult();

和Generator Promise方案看起來沒有太大區(qū)別,只是關(guān)鍵字換了換。

實(shí)際上async

function就是對(duì)Generator方案的一個(gè)官方認(rèn)可,將之作為語言內(nèi)置功能。

async function的缺點(diǎn):

await只能在async function內(nèi)部使用,因此一旦你寫了幾個(gè)async function,或者使用了依賴于async

function的庫,那你很可能會(huì)需要更多的async function。

目前處于提案階段的async

function還沒有得到任何瀏覽器或Node.JS/io.js的支持。Babel轉(zhuǎn)碼器也需要打開實(shí)驗(yàn)選項(xiàng),并且對(duì)于不支持Generator的瀏覽器來說,還需要引進(jìn)一層厚厚的regenerator

runtime,想在前端生產(chǎn)環(huán)境得到應(yīng)用還需要時(shí)間。

以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助。

ES6、ES7、ES8、ES9、ES10新特性一覽

ECMA規(guī)范最終由TC39敲定。TC39由包括瀏覽器廠商在內(nèi)的各方組成,他們開會(huì)推動(dòng)JavaScript提案沿著一條嚴(yán)格的發(fā)展道路前進(jìn)。 從提案到入選ECMA規(guī)范主要有以下幾個(gè)階段:

ES6的特性比較多,在 ES5 發(fā)布近 6 年(2009-11 至 2015-6)之后才將其標(biāo)準(zhǔn)化。兩個(gè)發(fā)布版本之間時(shí)間跨度很大,所以ES6中的特性比較多。 在這里列舉幾個(gè)常用的:

1.類(class)

對(duì)熟悉Java,object-c,c#等純面向?qū)ο笳Z言的開發(fā)者來說,都會(huì)對(duì)class有一種特殊的情懷。ES6 引入了class(類),讓JavaScript的面向?qū)ο缶幊套兊酶雍唵魏鸵子诶斫狻?/p>

2.模塊化(Module)

ES5不支持原生的模塊化,在ES6中模塊作為重要的組成部分被添加進(jìn)來。模塊的功能主要由 export 和 import 組成。每一個(gè)模塊都有自己單獨(dú)的作用域,模塊之間的相互調(diào)用關(guān)系是通過 export 來規(guī)定模塊對(duì)外暴露的接口,通過import來引用其它模塊提供的接口。同時(shí)還為模塊創(chuàng)造了命名空間,防止函數(shù)的命名沖突。

導(dǎo)出(export)

ES6允許在一個(gè)模塊中使用export來導(dǎo)出多個(gè)變量或函數(shù)。

導(dǎo)出變量

ES6將一個(gè)文件視為一個(gè)模塊,上面的模塊通過 export 向外輸出了一個(gè)變量。一個(gè)模塊也可以同時(shí)往外面輸出多個(gè)變量。

導(dǎo)出函數(shù)

導(dǎo)入(import)

定義好模塊的輸出以后就可以在另外一個(gè)模塊通過import引用。

3.箭頭(Arrow)函數(shù)

這是ES6中最令人激動(dòng)的特性之一。=不只是關(guān)鍵字function的簡寫,它還帶來了其它好處。箭頭函數(shù)與包圍它的代碼共享同一個(gè)this,能幫你很好的解決this的指向問題。有經(jīng)驗(yàn)的JavaScript開發(fā)者都熟悉諸如var self = this;或var that = this這種引用外圍this的模式。但借助=,就不需要這種模式了。

箭頭函數(shù)的結(jié)構(gòu)

箭頭函數(shù)的箭頭=之前是一個(gè)空括號(hào)、單個(gè)的參數(shù)名、或用括號(hào)括起的多個(gè)參數(shù)名,而箭頭之后可以是一個(gè)表達(dá)式(作為函數(shù)的返回值),或者是用花括號(hào)括起的函數(shù)體(需要自行通過return來返回值,否則返回的是undefined)。

卸載監(jiān)聽器時(shí)的陷阱

除上述的做法外,我們還可以這樣做:

4.函數(shù)參數(shù)默認(rèn)值

ES6支持在定義函數(shù)的時(shí)候?yàn)槠湓O(shè)置默認(rèn)值:

這樣寫一般沒問題,但當(dāng)參數(shù)的布爾值為false時(shí),就會(huì)有問題了。比如,我們這樣調(diào)用foo函數(shù):

foo(0, "")

因?yàn)?的布爾值為false,這樣height的取值將是50。同理color的取值為‘red’。

所以說,函數(shù)參數(shù)默認(rèn)值不僅能是代碼變得更加簡潔而且能規(guī)避一些問題。

5.模板字符串

ES6支持模板字符串,使得字符串的拼接更加的簡潔、直觀。

在ES6中通過${}就可以完成字符串的拼接,只需要將變量放在大括號(hào)之中。

6.解構(gòu)賦值

解構(gòu)賦值語法是JavaScript的一種表達(dá)式,可以方便的從數(shù)組或者對(duì)象中快速提取值賦給定義的變量。

獲取數(shù)組中的值

從數(shù)組中獲取值并賦值到變量中,變量的順序與數(shù)組中對(duì)象順序?qū)?yīng)。

如果沒有從數(shù)組中的獲取到值,你可以為變量設(shè)置一個(gè)默認(rèn)值。

通過解構(gòu)賦值可以方便的交換兩個(gè)變量的值。

獲取對(duì)象中的值

7.延展操作符(Spread operator)

延展操作符...可以在函數(shù)調(diào)用/數(shù)組構(gòu)造時(shí), 將數(shù)組表達(dá)式或者string在語法層面展開;還可以在構(gòu)造對(duì)象時(shí), 將對(duì)象表達(dá)式按key-value的方式展開。

語法

應(yīng)用場景

沒有展開語法的時(shí)候,只能組合使用 push,splice,concat 等方法,來將已有數(shù)組元素變成新數(shù)組的一部分。有了展開語法, 構(gòu)造新數(shù)組會(huì)變得更簡單、更優(yōu)雅:

和參數(shù)列表的展開類似, ... 在構(gòu)造字?jǐn)?shù)組時(shí), 可以在任意位置多次使用。

展開語法和 Object.assign() 行為一致, 執(zhí)行的都是淺拷貝(只遍歷一層)。

在ECMAScript 2018中延展操作符增加了對(duì)對(duì)象的支持

8.對(duì)象屬性簡寫

在ES6中允許我們?cè)谠O(shè)置一個(gè)對(duì)象的屬性的時(shí)候不指定屬性名。

對(duì)象中必須包含屬性和值,顯得非常冗余。

對(duì)象中直接寫變量,非常簡潔。

9.Promise

Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案callback更加的優(yōu)雅。它最早由社區(qū)提出和實(shí)現(xiàn)的,ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對(duì)象。

嵌套兩個(gè)setTimeout回調(diào)函數(shù):

上面的的代碼使用兩個(gè)then來進(jìn)行異步編程串行化,避免了回調(diào)地獄:

10.支持let與const

在之前JS是沒有塊級(jí)作用域的,const與let填補(bǔ)了這方便的空白,const與let都是塊級(jí)作用域。

ES2016添加了兩個(gè)小的特性來說明標(biāo)準(zhǔn)化過程:

1.Array.prototype.includes()

includes() 函數(shù)用來判斷一個(gè)數(shù)組是否包含一個(gè)指定的值,如果包含則返回 true,否則返回false。

includes 函數(shù)與 indexOf 函數(shù)很相似,下面兩個(gè)表達(dá)式是等價(jià)的:

接下來我們來判斷數(shù)字中是否包含某個(gè)元素:

使用indexOf()驗(yàn)證數(shù)組中是否存在某個(gè)元素,這時(shí)需要根據(jù)返回值是否為-1來判斷:

使用includes()驗(yàn)證數(shù)組中是否存在某個(gè)元素,這樣更加直觀簡單:

2.指數(shù)操作符

在ES7中引入了指數(shù)運(yùn)算符**,**具有與Math.pow(..)等效的計(jì)算結(jié)果。

使用自定義的遞歸函數(shù)calculateExponent或者M(jìn)ath.pow()進(jìn)行指數(shù)運(yùn)算:

使用指數(shù)運(yùn)算符**,就像+、-等操作符一樣:

1.async/await

ES2018引入異步迭代器(asynchronous iterators),這就像常規(guī)迭代器,除了next()方法返回一個(gè)Promise。因此await可以和for...of循環(huán)一起使用,以串行的方式運(yùn)行異步操作。例如:

2.Object.values()

Object.values()是一個(gè)與Object.keys()類似的新函數(shù),但返回的是Object自身屬性的所有值,不包括繼承的值。

假設(shè)我們要遍歷如下對(duì)象obj的所有值:

從上述代碼中可以看出Object.values()為我們省去了遍歷key,并根據(jù)這些key獲取value的步驟。

3.Object.entries()

Object.entries()函數(shù)返回一個(gè)給定對(duì)象自身可枚舉屬性的鍵值對(duì)的數(shù)組。

接下來我們來遍歷上文中的obj對(duì)象的所有屬性的key和value:

4.String padding

在ES8中String新增了兩個(gè)實(shí)例函數(shù)String.prototype.padStart和String.prototype.padEnd,允許將空字符串或其他字符串添加到原始字符串的開頭或結(jié)尾。

5.函數(shù)參數(shù)列表結(jié)尾允許逗號(hào)

主要作用是方便使用git進(jìn)行多人協(xié)作開發(fā)時(shí)修改同一個(gè)函數(shù)減少不必要的行變更。

6.Object.getOwnPropertyDescriptors()

Object.getOwnPropertyDescriptors()函數(shù)用來獲取一個(gè)對(duì)象的所有自身屬性的描述符,如果沒有任何自身屬性,則返回空對(duì)象。

返回obj對(duì)象的所有自身屬性的描述符,如果沒有任何自身屬性,則返回空對(duì)象。

7.SharedArrayBuffer對(duì)象

SharedArrayBuffer 對(duì)象用來表示一個(gè)通用的,固定長度的原始二進(jìn)制數(shù)據(jù)緩沖區(qū),類似于 ArrayBuffer 對(duì)象,它們都可以用來在共享內(nèi)存(shared memory)上創(chuàng)建視圖。與 ArrayBuffer 不同的是,SharedArrayBuffer 不能被分離。

8.Atomics對(duì)象

Atomics 對(duì)象提供了一組靜態(tài)方法用來對(duì) SharedArrayBuffer 對(duì)象進(jìn)行原子操作。

這些原子操作屬于 Atomics 模塊。與一般的全局對(duì)象不同,Atomics 不是構(gòu)造函數(shù),因此不能使用 new 操作符調(diào)用,也不能將其當(dāng)作函數(shù)直接調(diào)用。Atomics 的所有屬性和方法都是靜態(tài)的(與 Math 對(duì)象一樣)。

多個(gè)共享內(nèi)存的線程能夠同時(shí)讀寫同一位置上的數(shù)據(jù)。原子操作會(huì)確保正在讀或?qū)懙臄?shù)據(jù)的值是符合預(yù)期的,即下一個(gè)原子操作一定會(huì)在上一個(gè)原子操作結(jié)束后才會(huì)開始,其操作過程不會(huì)中斷。

wait() 和 wake() 方法采用的是 Linux 上的 futexes 模型(fast user-space mutex,快速用戶空間互斥量),可以讓進(jìn)程一直等待直到某個(gè)特定的條件為真,主要用于實(shí)現(xiàn)阻塞。

1.異步迭代

在async/await的某些時(shí)刻,你可能嘗試在同步循環(huán)中調(diào)用異步函數(shù)。例如:

這段代碼不會(huì)正常運(yùn)行,下面這段同樣也不會(huì):

這段代碼中,循環(huán)本身依舊保持同步,并在在內(nèi)部異步函數(shù)之前全部調(diào)用完成。

ES2018引入異步迭代器(asynchronous iterators),這就像常規(guī)迭代器,除了next()方法返回一個(gè)Promise。因此await可以和for...of循環(huán)一起使用,以串行的方式運(yùn)行異步操作。例如:

2.Promise.finally()

一個(gè)Promise調(diào)用鏈要么成功到達(dá)最后一個(gè).then(),要么失敗觸發(fā).catch()。在某些情況下,你想要在無論P(yáng)romise運(yùn)行成功還是失敗,運(yùn)行相同的代碼,例如清除,刪除對(duì)話,關(guān)閉數(shù)據(jù)庫連接等。

.finally()允許你指定最終的邏輯:

3.Rest/Spread 屬性

ES2015引入了Rest參數(shù)和擴(kuò)展運(yùn)算符。三個(gè)點(diǎn)(...)僅用于數(shù)組。Rest參數(shù)語法允許我們將一個(gè)不定數(shù)量的參數(shù)表示為一個(gè)數(shù)組。

展開操作符以相反的方式工作,將數(shù)組轉(zhuǎn)換成可傳遞給函數(shù)的單獨(dú)參數(shù)。例如Math.max()返回給定數(shù)字中的最大值:

ES2018為對(duì)象解構(gòu)提供了和數(shù)組一樣的Rest參數(shù)()和展開操作符,一個(gè)簡單的例子:

或者你可以使用它給函數(shù)傳遞參數(shù):

擴(kuò)展運(yùn)算符可以在其他對(duì)象內(nèi)使用,例如:

可以使用擴(kuò)展運(yùn)算符拷貝一個(gè)對(duì)象,像是這樣obj2 = {...obj1},但是 這只是一個(gè)對(duì)象的淺拷貝 。另外,如果一個(gè)對(duì)象A的屬性是對(duì)象B,那么在克隆后的對(duì)象cloneB中,該屬性指向?qū)ο驜。

4.正則表達(dá)式命名捕獲組

JavaScript正則表達(dá)式可以返回一個(gè)匹配的對(duì)象——一個(gè)包含匹配字符串的類數(shù)組,例如:以YYYY-MM-DD的格式解析日期:

這樣的代碼很難讀懂,并且改變正則表達(dá)式的結(jié)構(gòu)有可能改變匹配對(duì)象的索引。

ES2018允許命名捕獲組使用符號(hào)?name,在打開捕獲括號(hào)(后立即命名,示例如下:

任何匹配失敗的命名組都將返回undefined。

命名捕獲也可以使用在replace()方法中。例如將日期轉(zhuǎn)換為美國的 MM-DD-YYYY 格式:

5.正則表達(dá)式反向斷言

目前JavaScript在正則表達(dá)式中支持先行斷言(lookahead)。這意味著匹配會(huì)發(fā)生,但不會(huì)有任何捕獲,并且斷言沒有包含在整個(gè)匹配字段中。例如從價(jià)格中捕獲貨幣符號(hào):

ES2018引入以相同方式工作但是匹配前面的反向斷言(lookbehind),這樣我就可以忽略貨幣符號(hào),單純的捕獲價(jià)格的數(shù)字:

以上是 肯定反向斷言 ,非數(shù)字\D必須存在。同樣的,還存在 否定反向斷言 ,表示一個(gè)值必須不存在,例如:

6.正則表達(dá)式dotAll模式

正則表達(dá)式中點(diǎn).匹配除回車外的任何單字符,標(biāo)記s改變這種行為,允許行終止符的出現(xiàn),例如:

7.正則表達(dá)式 Unicode 轉(zhuǎn)義

到目前為止,在正則表達(dá)式中本地訪問 Unicode 字符屬性是不被允許的。ES2018添加了 Unicode 屬性轉(zhuǎn)義——形式為\p{...}和\P{...},在正則表達(dá)式中使用標(biāo)記 u (unicode) 設(shè)置,在\p塊兒內(nèi),可以以鍵值對(duì)的方式設(shè)置需要匹配的屬性而非具體內(nèi)容。例如:

此特性可以避免使用特定 Unicode 區(qū)間來進(jìn)行內(nèi)容類型判斷,提升可讀性和可維護(hù)性。

8.非轉(zhuǎn)義序列的模板字符串

之前,\\u開始一個(gè) unicode 轉(zhuǎn)義,\\x開始一個(gè)十六進(jìn)制轉(zhuǎn)義,\后跟一個(gè)數(shù)字開始一個(gè)八進(jìn)制轉(zhuǎn)義。這使得創(chuàng)建特定的字符串變得不可能,例如Windows文件路徑 C:\\uuu\\xxx\111。更多細(xì)節(jié)參考模板字符串。

1.行分隔符(U + 2028)和段分隔符(U + 2029)符號(hào)現(xiàn)在允許在字符串文字中,與JSON匹配

以前,這些符號(hào)在字符串文字中被視為行終止符,因此使用它們會(huì)導(dǎo)致SyntaxError異常。

2.更加友好的 JSON.stringify

如果輸入 Unicode 格式但是超出范圍的字符,在原先JSON.stringify返回格式錯(cuò)誤的Unicode字符串?,F(xiàn)在實(shí)現(xiàn)了一個(gè)改變JSON.stringify的第3階段提案,因此它為其輸出轉(zhuǎn)義序列,使其成為有效Unicode(并以UTF-8表示)

3.新增了Array的flat()方法和flatMap()方法

flat()和flatMap()本質(zhì)上就是是歸納(reduce) 與 合并(concat)的操作。

Array.prototype.flat()

flat() 方法會(huì)按照一個(gè)可指定的深度遞歸遍歷數(shù)組,并將所有元素與遍歷到的子數(shù)組中的元素合并為一個(gè)新數(shù)組返回。

Array.prototype.flatMap()

flatMap() 方法首先使用映射函數(shù)映射每個(gè)元素,然后將結(jié)果壓縮成一個(gè)新數(shù)組。它與 map 和 深度值1的 flat 幾乎相同,但 flatMap 通常在合并成一種方法的效率稍微高一些。 這里我們拿map方法與flatMap方法做一個(gè)比較。

4.新增了String的trimStart()方法和trimEnd()方法

5.Object.fromEntries()

Object.entries()方法的作用是返回一個(gè)給定對(duì)象自身可枚舉屬性的鍵值對(duì)數(shù)組,其排列與使用 for...in 循環(huán)遍歷該對(duì)象時(shí)返回的順序一致(區(qū)別在于 for-in 循環(huán)也枚舉原型鏈中的屬性)。

而Object.fromEntries() 則是 Object.entries() 的反轉(zhuǎn)。

Object.fromEntries() 函數(shù)傳入一個(gè)鍵值對(duì)的列表,并返回一個(gè)帶有這些鍵值對(duì)的新對(duì)象。這個(gè)迭代參數(shù)應(yīng)該是一個(gè)能夠?qū)崿F(xiàn)@iterator方法的的對(duì)象,返回一個(gè)迭代器對(duì)象。它生成一個(gè)具有兩個(gè)元素的類似數(shù)組的對(duì)象,第一個(gè)元素是將用作屬性鍵的值,第二個(gè)元素是與該屬性鍵關(guān)聯(lián)的值。

6.Symbol.prototype.description

通過工廠函數(shù)Symbol()創(chuàng)建符號(hào)時(shí),您可以選擇通過參數(shù)提供字符串作為描述:

以前,訪問描述的唯一方法是將符號(hào)轉(zhuǎn)換為字符串:

現(xiàn)在引入了getter Symbol.prototype.description以直接訪問描述:

7.String.prototype.matchAll

matchAll() 方法返回一個(gè)包含所有匹配正則表達(dá)式及分組捕獲結(jié)果的迭代器。 在 matchAll 出現(xiàn)之前,通過在循環(huán)中調(diào)用regexp.exec來獲取所有匹配項(xiàng)信息(regexp需使用/g標(biāo)志:

如果使用matchAll ,就可以不必使用while循環(huán)加exec方式(且正則表達(dá)式需使用/g標(biāo)志)。使用matchAll 會(huì)得到一個(gè)迭代器的返回值,配合 for...of, array spread, or Array.from() 可以更方便實(shí)現(xiàn)功能:

matchAll可以更好的用于分組

8.Function.prototype.toString()現(xiàn)在返回精確字符,包括空格和注釋

9.修改 catch 綁定

在 ES10 之前,我們必須通過語法為 catch 子句綁定異常變量,無論是否有必要。很多時(shí)候 catch 塊是多余的。 ES10 提案使我們能夠簡單的把變量省略掉。

不算大的改動(dòng)。

之前是

現(xiàn)在是

10.新的基本數(shù)據(jù)類型BigInt

現(xiàn)在的基本數(shù)據(jù)類型(值類型)不止5種(ES6之后是六種)了哦!加上BigInt一共有七種基本數(shù)據(jù)類型,分別是: String、Number、Boolean、Null、Undefined、Symbol、BigInt

JavaScript 的版本是怎么回事

JavaScript是 ECMAScript 標(biāo)準(zhǔn)的各種實(shí)現(xiàn)的最常用稱呼。這個(gè)術(shù)語并不局限于某個(gè)特定版本的 ECMAScript 規(guī)范,并且可能被用于任何不同程度的任意版本的 ECMAScript 的實(shí)現(xiàn)。被考慮加入未來版本 ECMAScript 標(biāo)準(zhǔn)的特性與語法提案,他們需要經(jīng)歷五個(gè)階段:Strawman(稻草人),Proposal(提議),Draft(草案),Candidate(候選)以及 Finished (完成)。


文章題目:javascript提案的簡單介紹
鏈接分享:http://weahome.cn/article/dsiegcc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部