摘要:本次我領(lǐng)到的任務(wù)是在中有一個(gè)解構(gòu)賦值運(yùn)算符,可以大大方便數(shù)據(jù)字段的獲取。解構(gòu)賦值運(yùn)算符配合會(huì)比較有用。
本次我領(lǐng)到的任務(wù)是:
在ES6中有一個(gè)解構(gòu)賦值運(yùn)算符,可以大大方便數(shù)據(jù)字段的獲取。 比如 const [a, b] = [1, 2, 3]; const {name, age} = {name: "helijia", age: 3}; 上面的語(yǔ)句是我們常用的,可是你能解釋為什么下面的語(yǔ)句也能正常工作嗎? const [a, b] = "abc"; const {toString: s} = 123; 任務(wù): 1. 解釋上面兩個(gè)解構(gòu)語(yǔ)句的工作原理 2. 你能夠?qū)崿F(xiàn)自定義類的數(shù)組解構(gòu)嗎? 比如: class A = … const a = new A(); const [e1, e2] = a; // 怎么樣才能讓自定義的類也能支持支持?jǐn)?shù)組的解構(gòu)呢?應(yīng)用 默認(rèn)值
ES5時(shí),處理默認(rèn)值的慣用法:
const scale = opts.scale || 1;
現(xiàn)在可以:
const {scale = 1} = opts;
不過(guò)兩者并不等價(jià),默認(rèn)值只會(huì)在目標(biāo)值是undefined時(shí)才會(huì)生效。
const {scale = 1} = {} // scale === 1 const {scale = 1} = {scale: null} // scale === null const {scale = 1} = {scale: undefined} // scale === 1交換
有個(gè)技巧是可以在一條語(yǔ)句內(nèi)實(shí)現(xiàn)變量值的交換。
原來(lái)需要三句話:
var tmp = a; var a = b; var b = a;
現(xiàn)在只需要:
const [a, b] = [b, a];
這讓我們?cè)趯?shí)現(xiàn)一些基礎(chǔ)算法時(shí)更加精練。
函數(shù)返回多個(gè)值在ES5中函數(shù)只能返回一個(gè)值,有了解構(gòu)賦值,可以模擬出多個(gè)返回值。
const [a, b] = f();
當(dāng)然從設(shè)計(jì)上說(shuō),js的函數(shù)的返回值還是應(yīng)該是單一的模型比較合適。
很小看到接口層面返回一個(gè)數(shù)組作為多個(gè)值。 可能在編寫(xiě)一些專業(yè)領(lǐng)域或DSL應(yīng)用時(shí)會(huì)用得到。
而在實(shí)現(xiàn)時(shí)經(jīng)常會(huì)使用解構(gòu)賦值帶來(lái)的便利:
const {name, age} = getInfo();忽略數(shù)組中的一些值
const [a, , c] = [1, 2, 3]; // a === 1 // c === c
我想到的一個(gè)應(yīng)用是一下子從正則表達(dá)式match對(duì)象中取出多個(gè)元素。
const re = /^([^=]+)=(.*)$/; const [, key, value] = re.exec("name=helijia"); // key === "name" // value === "helijia"spread
解構(gòu)賦值運(yùn)算符配合spread會(huì)比較有用。
const {name, age, ...exts} = item; return- ;
exts對(duì)象中并不包含name和age,如果在ES5中要費(fèi)好幾句語(yǔ)句。
數(shù)組也支持spread,但是數(shù)組本身具有slice等函數(shù),所以一般用不上。
var [head, ...tail] = [1, 2, 3, 4]; console.log(tail); // [2, 3, 4]重命名
對(duì)象的解構(gòu)還支持重新命名,這在名字沖突,或者簡(jiǎn)化代碼時(shí)會(huì)比較有用。
const item = { artisanNick: "玉米" artisanLevel: 10, artisanType: 3 }; const {artisanNick:nick, artisanLevel:level, artisanType:type} = item;
原來(lái)我們寫(xiě)成
const nick = item.artisanNick; const level = item.artisanLevel; const type = item.artisanType;
可配合默認(rèn)值一起用:
const {a:aa = 10, b:bb = 5} = {a: 3}函數(shù)參數(shù)的解構(gòu)
這在實(shí)際開(kāi)發(fā)中就用的比較多了,比如在React組件開(kāi)發(fā)中:
const Product = ({name, price}) => (babel對(duì)解構(gòu)賦值的支持);name: {name}price: {price}
以上描述的特性使用babel編譯器就能在主流瀏覽器中工作,babel對(duì)ES6的支持是通過(guò)將代碼編譯成ES5代碼來(lái)實(shí)現(xiàn)的;
而nodejs和chrome原生是直接支持es6的,它們是基于V8引擎在解釋器層面支持ES6,因此兩者能力是有差異的。
通過(guò)babel編譯的ES6,最后本質(zhì)是ES5代碼,是靜態(tài)的,所以只能支持一些語(yǔ)法糖的功能;
下面是一些示例:
常量// ES6 const [a, b, c, d] = [1, 2, 3, 4]; // 對(duì)應(yīng)的ES5 var a = 1; var b = 2; var c = 3; var d = 4;數(shù)組
// ES6 const list = [1, 2, 3, 4]; const [a, b, c, d] = list; // ES5 var list = [1, 2, 3, 4]; var a = list[0]; var b = list[1]; var c = list[2]; var d = list[3];別名和默認(rèn)值
// ES6 const {a:aa = 10, b:bb = 5} = {a: 3} // ES5 var _a = { a: 3 }; var _a$a = _a.a; var aa = _a$a === undefined ? 10 : _a$a; var _a$b = _a.b; var bb = _a$b === undefined ? 5 : _a$b;
重命名和默認(rèn)值的處理。
字符串// ES6 const [a, b, c] = "1234"; // ES5 var _ = "1234"; var a = _[0]; var b = _[1]; var c = _[2];
字符串也當(dāng)成數(shù)組一樣處理了,所以剛好正常工作。
迭代器其實(shí)只要實(shí)現(xiàn)迭代器接口,就能夠解構(gòu)。
const set = new Set([1, 2, 3, 4]) const [a, b, c] = set; console.log(a, b, c); // 1 2 3
這段代碼在chrome的cosnole和nodejs中都能正常工作,不過(guò)在babel中就歇菜了。
因?yàn)樗幾g后的結(jié)果為:
var set = new Set([1, 2, 3, 4]); var a = set[0]; var b = set[1]; var c = set[2]; console.log(a, b, c); // undefined undefined undefined
當(dāng)然Map也是實(shí)現(xiàn)了迭代器接口的。
const map = new Map(); map.set("window", window); map.set("document", document); for (const [key, value] of map) { console.log(key + " is " + value); } const [[k1, v1], [k2, v2]] = map; // destructring
再來(lái)一個(gè)例子:
function* iter() { yield 1; yield 2; yield 3; } const [a, b, c] = iter(); console.log(a, b, c); // 1 2 3
同樣這段代碼在babel中也不能正常工作。
回到任務(wù)const [a, b] = "abc"; const {toString: s} = 123; 任務(wù): 1. 解釋上面兩個(gè)解構(gòu)語(yǔ)句的工作原理 2. 你能夠?qū)崿F(xiàn)自定義類的數(shù)組解構(gòu)嗎?
所以以上兩個(gè)語(yǔ)句能正常工作,原因是分場(chǎng)景的,在通過(guò)babel編譯成ES5和通過(guò)解釋器直接執(zhí)行原理是不一樣的。
babel編譯器會(huì)把它編譯成
// ES6 const [a, b, c] = "1234"; const {toString: s} = "123"; // ES5 var _ = "1234"; var a = _[0]; var b = _[1]; var c = _[2]; var _2 = "123"; var s = _2.toString;
而js引擎執(zhí)行ES6是因?yàn)樽址畬?shí)現(xiàn)了迭代器接口,以及支持對(duì)象屬性訪問(wèn)。
對(duì)于第2個(gè)問(wèn)題,我們可以讓自定義類實(shí)現(xiàn)迭代器接口來(lái)支持,只是在babel中不能正常工作。
以下是一個(gè)示例:
class Random { [Symbol.iterator]() { return { next() { return {value: Math.random(), done: false}; } } } } const random = new Random(); for (const n of random) { if (n > 0.8) { break; } console.log(n); } const [e1, e2, e3, e4] = new Random(); console.log(e1, e2, e3, e4);規(guī)范和V8對(duì)解構(gòu)賦值的支持
運(yùn)行語(yǔ)義
看到數(shù)組的解構(gòu)處理,第一步總是取得一個(gè)迭代器,然后操作這個(gè)迭代器。
從規(guī)范中知道,解構(gòu)賦值操作符對(duì)應(yīng)的元素就是 DestructuringAssignment,查詢V8代碼可知,
V8在parser階段就會(huì)把解構(gòu)賦值語(yǔ)句重寫(xiě)成等效的賦值語(yǔ)句, 這樣解釋器不需要做修改就可以運(yùn)行新的語(yǔ)法,也保證了效率。
關(guān)鍵代碼片段:
RewriteDestructuringAssignments
RewriteDestructuringAssignment
VisitArrayLiteral
Pattern Match使用了近一年半的Elixir,有許多語(yǔ)言特性另人著迷,其中模式匹配就是一個(gè)。
在ES6中引入了和模式匹配語(yǔ)法有點(diǎn)接近的解構(gòu)賦值(Destructring Assigmnent)語(yǔ)句,但是僅僅是部分精簡(jiǎn)代碼的語(yǔ)法糖,而在語(yǔ)義和表達(dá)上并沒(méi)有本質(zhì)變化。
不過(guò)搜索github上,看到已有相關(guān)的proposal,以及babel實(shí)現(xiàn)的issue,所以借此機(jī)會(huì)熟悉了解一番。
另外發(fā)現(xiàn)一個(gè)js庫(kù)js-pattern-matching,提供了一個(gè)函數(shù)來(lái)支持模式匹配
其中這個(gè)JS庫(kù)在不引入新語(yǔ)法特性的基礎(chǔ)上支持較好的模式匹配語(yǔ)法,我覺(jué)得挺贊的。 它的原理是利用function.toString,得到函數(shù)字符串,再生成匹配的新的函數(shù)。
我寫(xiě)了幾個(gè)簡(jiǎn)單的示例試用了一下,感覺(jué)還不錯(cuò),不過(guò)在類型匹配時(shí)有些BUG。
基于解構(gòu)賦值的匹配const match = require("js-pattern-matching"); const sum = (list) => match(list) ( ([x,...xs]) => x + sum(xs), ([]) => 0 ); console.log(sum([])); console.log(sum([1, 2, 3, 4]));常量匹配
因?yàn)橐险Z(yǔ)法,所以加個(gè)前續(xù)v=,文檔說(shuō)是可改成其他字母。
const fibs = (n) => match(n) ( (v= 0) => 0, (v= 1) => 1, _ => fibs(n - 2) + fibs(n - 1) ); for (let i = 0; i < 10; i++) { console.log(fibs(i)); }類型匹配
const type = (v) => match(v) ( (Array) => "array", (Object) => "object", _ => "unknow" );
我也看了proposal的語(yǔ)法,感覺(jué)風(fēng)格和原來(lái)的js差異太大,設(shè)計(jì)成Expression,可以在任何地方使用,可能會(huì)因?yàn)楣δ芴珡?qiáng)而導(dǎo)致濫用,反而起不到原來(lái)模式匹配優(yōu)雅簡(jiǎn)潔的目的。
其他人的一些探索,不過(guò)這個(gè)語(yǔ)法不是很美觀。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90286.html
摘要:變量的解構(gòu)賦值數(shù)組的解構(gòu)賦值允許寫(xiě)成下面這樣本質(zhì)上,這種寫(xiě)法屬于模式匹配,只要等號(hào)兩邊的模式相同,左邊的變量就會(huì)被賦予對(duì)應(yīng)的值。對(duì)象的解構(gòu)賦值對(duì)象的解構(gòu)與數(shù)組有一個(gè)重要的不同。由于和無(wú)法轉(zhuǎn)為對(duì)象,所以對(duì)他們進(jìn)行解構(gòu)賦值,都會(huì)報(bào)錯(cuò)。 變量的解構(gòu)賦值 數(shù)組的解構(gòu)賦值 let a = 1; let b = 2; let c = 3; ES6允許寫(xiě)成下面這樣 let [a,b,c] = [1,...
摘要:數(shù)組的解構(gòu)賦值特點(diǎn)根據(jù)數(shù)據(jù)的下標(biāo)來(lái)賦值的,有次序。模式能夠匹配起來(lái),如長(zhǎng)度為數(shù)值和布爾值的解構(gòu)賦值解構(gòu)賦值的規(guī)則是只要等號(hào)右邊的值不是對(duì)象或數(shù)組,就先將其轉(zhuǎn)為對(duì)象。布爾值解構(gòu)賦值為字符串的一種。在很多獨(dú)立細(xì)小的方面,解構(gòu)賦值都非常有用。 1、解構(gòu)賦值簡(jiǎn)介 官方解釋:按照一定的模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,這被稱為解構(gòu)(Destructuring)。 舉個(gè)例子,想獲取數(shù)組中...
摘要:模板字符串甚至還能嵌套解構(gòu)賦值允許按照一定模式,從數(shù)組和對(duì)象中提取值,對(duì)變量進(jìn)行賦值,這被稱為解構(gòu)。運(yùn)算符使用場(chǎng)景應(yīng)該稍少一些,主要是處理不定數(shù)量參數(shù),可以避免對(duì)象的使用。 es6中較為常用的書(shū)寫(xiě)風(fēng)格 為了書(shū)寫(xiě)的方便,es6中提出了很多比較友好的書(shū)寫(xiě)方式,其中最為常見(jiàn)的屬于以下幾個(gè): 字符串模板 `abcdef${test}` 解構(gòu)賦值 let [a, b, c] = [1,...
摘要:被解構(gòu)的數(shù)據(jù)項(xiàng)位于賦值運(yùn)算符的右側(cè),可以是任何數(shù)組和對(duì)象的組合,允許隨意嵌套。數(shù)組模式位于賦值運(yùn)算符的左側(cè),被結(jié)構(gòu)的數(shù)組在其右側(cè)。 解構(gòu)是ES6的新特性,用于從JavaScript對(duì)象和數(shù)組中提取數(shù)據(jù),語(yǔ)法上比ES5所提供的更加簡(jiǎn)潔、緊湊、清晰。它不僅能減少你的代碼量,還能從根本上改變你的編碼方式。用的越多,你就會(huì)發(fā)現(xiàn)越多塑造數(shù)據(jù)和函數(shù)的方式,這些實(shí)現(xiàn)方式在過(guò)去幾乎是不可能的。本文將深...
摘要:在語(yǔ)法中,操作符有兩種意義剩余語(yǔ)法,參數(shù)和展開(kāi)語(yǔ)法,展開(kāi)數(shù)組對(duì)象,作為函數(shù)數(shù)組對(duì)象的擴(kuò)展運(yùn)算符。使用和參數(shù)進(jìn)行操作其余參數(shù)傳給原始函數(shù)展開(kāi)語(yǔ)法運(yùn)算則可以看作是參數(shù)的逆運(yùn)算。 在ES6語(yǔ)法中,...操作符有兩種意義:rest(剩余語(yǔ)法,rest參數(shù)) 和 spread(展開(kāi)語(yǔ)法,展開(kāi)數(shù)組/對(duì)象),作為函數(shù)、數(shù)組、對(duì)象的擴(kuò)展運(yùn)算符。 從某種意義上說(shuō),剩余語(yǔ)法與展開(kāi)語(yǔ)法是相反的:剩余語(yǔ)法將多...
閱讀 2938·2023-04-26 02:22
閱讀 2292·2021-11-17 09:33
閱讀 3144·2021-09-22 16:06
閱讀 1078·2021-09-22 15:54
閱讀 3541·2019-08-29 13:44
閱讀 1921·2019-08-29 12:37
閱讀 1327·2019-08-26 14:04
閱讀 1920·2019-08-26 11:57