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