摘要:以前現(xiàn)在創(chuàng)建一個(gè)叫做的變量,值是數(shù)組中第一個(gè)對(duì)象中鍵的值。以前用的時(shí)候使用鏈?zhǔn)絹?lái)處理這種連續(xù)請(qǐng)求。一個(gè)可以一個(gè),并且等待結(jié)果以后再進(jìn)行下一步。并且一請(qǐng)求到就立即打印結(jié)果,并不等待后續(xù)的請(qǐng)求完成。
String Template Strings
連接String更方便直觀。使用反引號(hào)包括要生成的String,使用${}包括具體變量。
var name = "Yixuan"; var email = "[email protected]"; var title = "Student"; //以前 var msg = "Welcome! Your " + title + " is " + name + ", contact: " + email + "."; //現(xiàn)在 var msg = `Welcome! Your ${title} is ${name}, contact: ${email}.` //Welcome! Your name is Yixuan, contact: [email protected].Tagged Templates
在模版字符串前調(diào)用自定函數(shù),來(lái)定制模版字符串的解析方式。這個(gè)函數(shù)的第一個(gè)函數(shù)包含一個(gè)字符串值的數(shù)組,其余的參數(shù)是一系列的$表達(dá)式的引用變量,可以用...操作來(lái)把這些參數(shù)當(dāng)成一個(gè)數(shù)組。
這個(gè)例子中我們的自定函數(shù)formatCurrency將字符串中的數(shù)字加上了$符號(hào)并保留兩位小數(shù)。
var amount = 4.2; var msg = formatCurrency`The total for your order is ${amount}.` function formatCurrency(strings, ...values) { var str = ""; //console.log(strings); for (let i = 0; i < strings.length; i++) { str += strings[i]; if( i < values.length){ console.log(typeof values[i]); if(typeof values[i] == "number") { str += `$${values[i].toFixed(2)}`; }else { str += values[i]; } } } return str; } console.log(msg); //The total for your order is $12.30.String Padding & String Trimming
JS標(biāo)準(zhǔn)庫(kù)中現(xiàn)在自帶給字符串兩邊加內(nèi)容和刪減空格的方法。
padStart給字符串左邊加內(nèi)容,padEnd給字符串右邊加內(nèi)容。
var str = "Hello"; str.padStart(5); // "Hello" str.padStart(8) // " Hello" str.padStart(8, "*"); // "***Hello" str.padStart(8, "12345"); // "123Hello" str.padStart(8, "ab"); // abaHello" str.padEnd(8) // "Hello " str.padEnd(8, "*") // "Hello***" str.padEnd(8, "ab"); // "Helloaba"
trimStart去除左邊空格, trimEnd去除右邊空格。
var str = " some stuff "; str.trim(); // "some stuff" str.trimStart(); // "some stuff " str.trimEnd(); // " some stuff"Destructuring
有時(shí)我們get到了一個(gè)很大的JSON對(duì)象,我們需要把里面的一些值分配到變量當(dāng)中。解構(gòu)讓這個(gè)操作更方便。
看一個(gè)例子。
var tmp = getSomeRecords(); //tmp是一個(gè)擁有兩個(gè)對(duì)象的數(shù)組。 //以前 var first = tmp[0]; var second = tmp[1]; var firstName = first.name; var firstEmail = first.email !== undefined ? first.email : "no email"; var secondName = second.name; var secondEmail = second.email !== undefined ? first.email : "no email"; //現(xiàn)在 var [ {// 創(chuàng)建一個(gè)叫做firstName的變量,值是數(shù)組中第一個(gè)對(duì)象中name鍵的值。 name: firstName, // 創(chuàng)建一個(gè)叫做firstEmail的變量,值是數(shù)組中第一個(gè)對(duì)象中email鍵的值,如果沒(méi)有這個(gè)鍵則使用默認(rèn)值“no email"。 email: firstEmail = "no email" }, { name: secondName, email: secondEmail = "no email" } ] = tmp;
注意在這個(gè)例子中,賦值等號(hào)左邊的[],這個(gè)中括號(hào)不代表數(shù)組,而代表一種解構(gòu)賦值的pattern模式。還有要注意的是像上面這個(gè)例子的email的默認(rèn)值只會(huì)在檢測(cè)到undefined的時(shí)候才會(huì)被使用,如果值是null,不會(huì)觸發(fā)使用默認(rèn)值。
看一個(gè)更簡(jiǎn)單的例子。
function data(){ return [1,2,3]; } // 以前 var tmp = data(); var first = tmp[0]; var second = tmp[1]; var third = tmp[2]; //現(xiàn)在 var [ first, second, third ] = data();
如果左邊的變量比右邊的值多,多余的變量的值就會(huì)是undefined。如果左邊的變量比右邊的值少,多余的值會(huì)被忽略。
如果我們要在一個(gè)變量里多賦幾個(gè)值呢?
data = [1,2,3,4,5]; var [ first, second, third, ...fourth ] = data; //這里fourth是[4,5];
如果值不夠
data =[1,2,3]; var [ first, second, third, ...fourth ] = data; //這里fourth是空數(shù)組[];
有的時(shí)候我們需要交換變量的值,用解構(gòu)也更方便。
var x = 10; var y = 20; //以前 var tmp = x; x = y; y = tmp; //現(xiàn)在 ] [y,x] = [x,y];
有的時(shí)候我們將一個(gè)數(shù)組傳入函數(shù)的時(shí)候,我們只需要它的前三個(gè)元素,我們也可以使用解構(gòu),在函數(shù)參數(shù)聲明的時(shí)候就做到這步。
function data([ first, second, third ]) { }
解構(gòu)賦值如果出現(xiàn)賦值錯(cuò)誤,和普通賦值一樣,也會(huì)報(bào)錯(cuò)。
var data = null; var [first, second] = data; //TypeError function foo([first,second]) } { ... } foo(data);//傳入null //TypeError
這個(gè)時(shí)候我們需要Graceful Fallback(降級(jí),向下兼容)
var data = null; var [first, second] = data || []; //不報(bào)錯(cuò) function foo([first,second] = []) } { ... } //不報(bào)錯(cuò)
嵌套解構(gòu)
var data = [1,[2,3],4]; var [ first, [ second, third ], fourth ] = data;Object Destructuring
有的時(shí)候我們有一個(gè)默認(rèn)的對(duì)象,但是我們需要根據(jù)一個(gè)新傳過(guò)來(lái)的對(duì)象,來(lái)創(chuàng)建一個(gè)新對(duì)象。舉個(gè)例子,我們知道的表單信心有name,wechat,phone,gender等屬性(鍵名),但是有時(shí)表單會(huì)有新的屬性。這是我們可以用解構(gòu)賦值來(lái)很好的創(chuàng)建出一個(gè)新對(duì)象,來(lái)傳到后端或傳到數(shù)據(jù)庫(kù)。
function makeObject({ name = "default name", wechat = "default wechat", phone = "default phone", gender = "none", ...otherProps } = {}) { return { name, wechat, phone, gender, ...otherProps } } const obj = { name: "wyx", wechat: "weixin", gender: "male", age:"22", year:"2019" } const newObj = makeObject(obj); console.log(newObj); /* { name: "wyx", wechat: "weixin", phone: "default phone",//沒(méi)有的屬性使用默認(rèn)值 gender: "male", age: "22", year: "2019" } */Array Array.find()
找到數(shù)組中相應(yīng)的值,如果有就返回這個(gè)值,沒(méi)有就undefined。
var arr = [{a:1},{a:2}]; var res = arr.find(v => v && v.a > 1); console.log(res); // {a:2} res = arr.find(v => v && v.a > 10); console.log(res); // undefinedArray.findIndex()
找到相應(yīng)值的index
var arr = ["a","b","c","d"]; var res = arr.findIndex(v => v && v == "c"); console.log(res); // 2 res = arr.findIndex(v => v && v == "x"); console.log(res); // -1Array.includes()
用來(lái)代替以前的Array.indexOf(xxx) != -1
var arr = [10,20,30,40]; //以前 if(arr.indexOf(30) != -1){ console.log("exist!"); } //現(xiàn)在 if(arr.includes(30)) { console.log("exist!"); } //exist!Array.flat()
攤開(kāi)數(shù)組,可以根據(jù)傳入?yún)?shù)改變具體攤開(kāi)的層數(shù)。默認(rèn)攤開(kāi)一層。
var nestedArray = [1,2,[3,4],[5,[6,7]]]; nestedValues.flat(0); //[1,2,[3,4],[5,[6,7]]] nestedValues.flat(); //default 1 //[1,2,3,4,5,[6,7]] nestedValues.flat(2); //[1,2,3,4,5,6,7];Array.flatMap()
flatMap只能攤開(kāi)一層,如果需要更多層,需要分開(kāi)使用map()和flat().
[1,2,3,4,5,6].flatMap(v => { if (v % 2 == 0) { return [v, v * 2]; } else { return []; } }) //[2,4,4,8,6,12]Iterator Built-in Iterable
Iterator簡(jiǎn)單來(lái)說(shuō),就是我們用next()來(lái)遍歷一個(gè)集合。
在ES6中,String, Array, TypedArray,Map, Set是默認(rèn)iterable的。
var str = "Hi" //在string上使用iterator var it1 = str[Symbol.iterator](); //這里Symbol.iterator是str對(duì)象的一個(gè)屬性,我們通過(guò)[Symbol.iterator]獲取到這個(gè)對(duì)象的iterator然后把它賦給it1。 it1.next(); // { value: "H", done: false} it2.next(); // { value: "i", done: false} it3.next(); // { valye: undefinedn done:true} var arr = ["H","i"]; //在Array上使用iterator var it2 = arr[Symbol.iterator](); it2.next(); // {value : "H", done: false} it2.next(); // {value : "i", done: false} it2.next(); // {value : undefined, done: true}Declarative Iterators
for of 循環(huán)其實(shí)就是使用了iterator
var str = "Hello"; var it = str[Symbol.iterator](); //在for loop中使用iterator for(let v of it){ console.log(v); } //效果和直接使用for loop是一樣的 for (let v of str) { console.log(v); }
...符號(hào)也使用iterator
var str ="Hello"; var letters = [...str]; console.log(letters); // ["H","e","l","l","o"]Object類型沒(méi)有iterator
我們?cè)趈s中最常使用的對(duì)象類型,沒(méi)有默認(rèn)的iterator,我們需要自己定義一個(gè)。
var obj = { a : 1, b : 2, c : 3 } for (let v of obj) { console.log(v); } // TypeError! //想要使用for of循環(huán)的時(shí)候出現(xiàn)了錯(cuò)誤 //定義iterator屬性 obj[Symbol.iterator] = function(){ let keys = Object.keys(this); let index = 0; return { next: () => { if(index < keys.length){ return { done : false, value : keys[index++] } }else { return { done : true, value : undefined } } } }; } console.log([...obj]); //["a","b","c"]Generators Generators
function *generate() { yield 1; yield 2; yield 3; return 4; } var it = generate(); it.next(); // {value: 1, done : false} it.next(); // {value: 2, done : false} it.next(); // {value: 3, done : false} it.next(); // {value: 4, done : true} console.log([...generate()]); // [1,2,3]
一個(gè)使用生成器的例子,這里我們給luckyNumbers對(duì)象一個(gè)我們自定義的生成器函數(shù)叫l(wèi)ucky,然后在調(diào)用這個(gè)生成器的時(shí)候使用...操作符來(lái)iterate這個(gè)生成器,打印1-30之間6的倍數(shù)。
var luckyNumbers = { *lucky({ start = 0, end = 100, step = 1 } = {}) { for (let i = start; i <= end; i+= step) { yield i; } } }; console.log(`My lucky numbers are: ${ [...luckyNumbers.lucky({ start: 6, end: 30, step: 4 })] }`) //My lucky numbers are: 6,10,14,18,22,26,30Async Await Async出現(xiàn)的歷史
這里有一個(gè)例子,我們先請(qǐng)求當(dāng)前當(dāng)前用戶,獲得用戶數(shù)據(jù)以后,又請(qǐng)求當(dāng)前用戶所下過(guò)訂單和進(jìn)行中的訂單的例子。
以前用Promise的時(shí)候,使用鏈?zhǔn)絫hen()來(lái)處理這種連續(xù)請(qǐng)求。
fetchCurrentUser() .then(function onUser(user) { //獲得當(dāng)前用戶 return Promise.all([ //用Promise.all來(lái)做兩個(gè)請(qǐng)求,返回的還是一個(gè)promise,如果有一個(gè)請(qǐng)求中有一個(gè)reject則都reject fetchArchivedOrders( user.id ), fetchCurrentOrders (user.id) ]); })
后來(lái)我們有人不再用鏈?zhǔn)絫hen()來(lái)處理多個(gè)請(qǐng)求。而是用generator來(lái)獲得多個(gè)請(qǐng)求的response。一個(gè)generator可以yield一個(gè)promise,并且等待yield結(jié)果以后再進(jìn)行下一步。但是這個(gè)方法一般要使用第三方庫(kù)的一種runner函數(shù)進(jìn)行,像Co,Koa都有。runner函數(shù)的作用就是在yield的時(shí)候等待結(jié)果resolve,然后再往下iterate,往下yield。
runner(function *main() { var user = yield fetchCurrentUser(); var [ archivedOrders, currentOrders ] = yield Promise.all([ fetchArchivedOrders( user.id ), fetchArchivedOrders( user.id ) ]) });
其實(shí)上面這個(gè)例子里的yield關(guān)鍵詞,已經(jīng)很像await關(guān)鍵詞了,所以后來(lái)JS官方就推出了Async Await關(guān)鍵詞,不再需要用第三方庫(kù)的runner函數(shù)。
async function main() { var user = await fectchCurrentUser(); var [archiveOrders, currentOrders] = await Promise.all([ fetchArchiveOrders(user.id), fetchCurrentOrders(user.id) ]); return archiveOrders + currentOrders; }
這里有個(gè)例子,我們同時(shí)請(qǐng)求三個(gè)file,但是保證打印結(jié)果是按順序打印,也沒(méi)有undefined。并且一請(qǐng)求到就立即打印結(jié)果,并不等待后續(xù)的請(qǐng)求完成。
function getFile(file) { return new Promise(function(resolve){ fakeAjax(file,resolve); }); } async function loadFiles(files) { var prs = files.map(getFile); //用map同時(shí)做三個(gè)請(qǐng)求 for (let pr of prs) { console.log(await pr); } //在for loop中加入await關(guān)鍵詞,來(lái)確保按順序打印,也不會(huì)undefined。 } loadFiles(["files","file2","file3"]);async await problems
async await也有一些問(wèn)題
await只能應(yīng)對(duì)Promise
Starvation
promise會(huì)在時(shí)間循環(huán)中排進(jìn)microtask,會(huì)造成饑餓陷阱,這里不多寫。
cancelation
Async函數(shù)是沒(méi)有辦法被手動(dòng)取消的,比如一個(gè)request要下載巨大的文件,async函數(shù)過(guò)程就會(huì)一直進(jìn)行
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/104670.html
摘要:學(xué)習(xí)定稿有兩年多的時(shí)間了,斷斷續(xù)續(xù)通過(guò)一些博客,書(shū)籍也學(xué)到了很多知識(shí)。將各個(gè)部分的知識(shí)整理成一篇篇博文,以便于自己系統(tǒng)掌握和復(fù)習(xí)。整個(gè)系列主要參考了的深入理解,可以看作是對(duì)這本書(shū)的一個(gè)學(xué)習(xí)總結(jié),也向大家強(qiáng)烈推薦這本書(shū)作為的學(xué)習(xí)書(shū)籍。 學(xué)習(xí)es6 es6定稿有兩年多的時(shí)間了,斷斷續(xù)續(xù)通過(guò)一些博客,書(shū)籍也學(xué)到了很多es6知識(shí)。可以說(shuō),es6給js語(yǔ)言帶來(lái)了非常大的改進(jìn),引進(jìn)了很多好用的特性...
摘要:聲明之函數(shù)作用域和全局作用域。塊級(jí)作用域不能重復(fù)聲明臨時(shí)性死區(qū)等特性用來(lái)解決變量存在的種種問(wèn)題。塊級(jí)作用域終于在外面訪問(wèn)不到了。一些常量聲明使用聲明的變量名全部大寫。 ES5之前javascript語(yǔ)言只有函數(shù)作用域和全局作用域,使用var來(lái)聲明變量,var聲明的變量還存在變量提升使人困惑不已。我們先來(lái)復(fù)習(xí)一下ES5的var聲明,再對(duì)比學(xué)習(xí)let和const 。 var var聲明之函...
摘要:結(jié)合工作中使用情況,簡(jiǎn)單對(duì)進(jìn)行一些復(fù)習(xí)總結(jié),包括常用的語(yǔ)法,等,以及短時(shí)間內(nèi)要上手需要重點(diǎn)學(xué)習(xí)的知識(shí)點(diǎn)不同工作環(huán)境可能有一些差別,主要參考鏈接是阮一峰的博客以及外文博客阮老師大部分文章是直接翻譯的這個(gè)博客簡(jiǎn)介先說(shuō)一下,是一個(gè)標(biāo)準(zhǔn)化組織,他們 結(jié)合工作中使用情況,簡(jiǎn)單對(duì)es6進(jìn)行一些復(fù)習(xí)總結(jié),包括常用的語(yǔ)法,api等,以及短時(shí)間內(nèi)要上手需要重點(diǎn)學(xué)習(xí)的知識(shí)點(diǎn)(不同工作環(huán)境可能有一些差別),...
摘要:的暑期實(shí)習(xí)面試到現(xiàn)在差不多都結(jié)束了,算下來(lái)自己也投了十幾家簡(jiǎn)歷,經(jīng)歷的差不多十場(chǎng)筆試,現(xiàn)場(chǎng)和電話面試也差不多有五六家公司。阿里三面三面不知道是不是交叉面,不過(guò)這次面試面試官說(shuō)他是北京的之前都是杭州。 2017的暑期實(shí)習(xí)面試到現(xiàn)在差不多都結(jié)束了,算下來(lái)自己也投了十幾家簡(jiǎn)歷,經(jīng)歷的差不多十場(chǎng)筆試,現(xiàn)場(chǎng)和電話面試也差不多有五六家公司。雖然最后只拿到兩個(gè)offer,所幸是自己期待的公司,下面從...
閱讀 1496·2019-08-30 15:44
閱讀 1956·2019-08-30 14:07
閱讀 2883·2019-08-30 13:56
閱讀 2355·2019-08-29 17:06
閱讀 1336·2019-08-29 14:13
閱讀 2093·2019-08-29 11:28
閱讀 3241·2019-08-26 13:56
閱讀 1960·2019-08-26 12:11