您好,登錄后才能下訂單哦!
今天就跟大家聊聊有關怎么在JavaScript中實現(xiàn)一個數(shù)組惰性求值庫,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
javascript是一種動態(tài)類型、弱類型的語言,基于對象和事件驅動并具有相對安全性并廣泛用于客戶端網(wǎng)頁開發(fā)的腳本語言,同時也是一種廣泛用于客戶端Web開發(fā)的腳本語言。它主要用來給HTML網(wǎng)頁添加動態(tài)功能,現(xiàn)在JavaScript也可被用于網(wǎng)絡服務器,如Node.js。
惰性求值每次求值的時候并不是返回數(shù)值,而是返回一個包含計算參數(shù)的求值函數(shù),每次到了要使用值得時候,才會進行計算。
當有多個惰性操作的時候,構成一個求值函數(shù)鏈,每次求值的時候,每個求值函數(shù)都向上一個求值函數(shù)求值,返回一個值。最后當計算函數(shù)終止的時候,返回一個終止值。
每次求值函數(shù)都會返回各種數(shù)據(jù),所以得使用一個獨一無二的值來作為判斷流是否完成的標志。剛好 Symbol() 可以創(chuàng)建一個新的 symbol ,它的值與其它任何值皆不相等。
const over = Symbol(); const isOver = function (_over) { return _over === over; }
range 函數(shù)接受一個起始和終止參數(shù),返回一個求值函數(shù),運行求值函數(shù)返回一個值,終止的時候返回終止值。
const range = function (from, to) { let i = from; return function () { if (i < to) { i++ console.log('range\t', i); return i } return over; } }
接受一個求值函數(shù)和處理函數(shù),獲取求值函數(shù) flow 中的數(shù)據(jù),對數(shù)據(jù)進行處理,返回一個流。
const map = function (flow, transform) { return function () { const data = flow(); console.log('map\t', data); return isOver(data) ? data : transform(data); } }
接受一個求值函數(shù),對求值函數(shù) flow 中數(shù)據(jù)進行過濾,找到符合的數(shù)據(jù)并且返回。
const filter = function (flow, condition) { return function () { while(true) { const data = flow(); if (isOver(data)) { return data; } if(condition(data)) { console.log('filter\t', data); return data; } } } }
接受一個求值函數(shù),當達到某個條件時中斷,可以用閉包函數(shù)加上 stop 函數(shù)接著實現(xiàn)一個 take 函數(shù)。
const stop = function (flow, condition) { let _stop = false; return function () { if (_stop) return over; const data = flow(); if (isOver(data)) { return data; } _stop = condition(data); return data; } } const take = function(flow, num) { let i = 0; return stop(flow, (data) => { return ++i >= num; }); }
因為返回的都是一個函數(shù),最后得使用一個 join 函數(shù)來收集所有的值并且返回一個數(shù)組。
const join = function (flow) { const array = []; while(true) { const data = flow(); if (isOver(data)) { break; } array.push(data); } return array; }
const nums = join(take(filter(map(range(0, 20), n => n * 10), n => n % 3 === 0), 2)); console.log(nums);
輸出:
range 1
map 1
range 2
map 2
range 3
map 3
filter 30
range 4
map 4
range 5
map 5
range 6
map 6
filter 60
上面使用 函數(shù) + 閉包 實現(xiàn)了惰性求值,但是還是不夠優(yōu)雅,絕大部分代碼都放到迭代和判斷求值是否完成上面去了。其實 es6 中還有更好方法來實現(xiàn)惰性求值,就是使用 generator,generator 已經(jīng)幫我們解決了迭代和判斷流是否完成,我們就可以專注于邏輯,寫出更簡潔易懂結構清晰的代碼。
const range = function* (from, to) { for(let i = from; i < to; i++) { console.log('range\t', i); yield i; } } const map = function* (flow, transform) { for(const data of flow) { console.log('map\t', data); yield(transform(data)); } } const filter = function* (flow, condition) { for(const data of flow) { console.log('filter\t', data); if (condition(data)) { yield data; } } } const stop = function*(flow, condition) { for(const data of flow) { yield data; if (condition(data)) { break; } } } const take = function (flow, number) { let count = 0; const _filter = function (data) { count ++ return count >= number; } return stop(flow, _filter); }
還得加上鏈式調(diào)用才算是完成了。
class _Lazy{ constructor() { this.iterator = null; } range(...args) { this.iterator = range(...args); return this; } map(...args) { this.iterator = map(this.iterator, ...args); return this; } filter(...args) { this.iterator = filter(this.iterator, ...args); return this; } take(...args) { this.iterator = take(this.iterator, ...args); return this; } [Symbol.iterator]() { return this.iterator; } } function lazy () { return new _Lazy(); }
最后再測試一下:
const nums = lazy().range(0, 100).map(n => n * 10).filter(n => n % 3 === 0).take(2); for(let n of nums) { console.log('num:\t', n, '\n'); }
輸出:
range 0
map 0
filter 0
num: 0
range 1
map 1
filter 10
range 2
map 2
filter 20
range 3
map 3
filter 30
num: 30
看完上述內(nèi)容,你們對怎么在JavaScript中實現(xiàn)一個數(shù)組惰性求值庫有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內(nèi)容。