溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在JavaScript中實現一個數組惰性求值庫

發布時間:2021-05-06 16:31:36 來源:億速云 閱讀:148 作者:Leah 欄目:開發技術

今天就跟大家聊聊有關怎么在JavaScript中實現一個數組惰性求值庫,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

javascript是一種什么語言

javascript是一種動態類型、弱類型的語言,基于對象和事件驅動并具有相對安全性并廣泛用于客戶端網頁開發的腳本語言,同時也是一種廣泛用于客戶端Web開發的腳本語言。它主要用來給HTML網頁添加動態功能,現在JavaScript也可被用于網絡服務器,如Node.js。

惰性求值每次求值的時候并不是返回數值,而是返回一個包含計算參數的求值函數,每次到了要使用值得時候,才會進行計算。

怎么在JavaScript中實現一個數組惰性求值庫

當有多個惰性操作的時候,構成一個求值函數鏈,每次求值的時候,每個求值函數都向上一個求值函數求值,返回一個值。最后當計算函數終止的時候,返回一個終止值。

怎么在JavaScript中實現一個數組惰性求值庫

具體實現

判斷求值函數終止

每次求值函數都會返回各種數據,所以得使用一個獨一無二的值來作為判斷流是否完成的標志。剛好 Symbol() 可以創建一個新的 symbol ,它的值與其它任何值皆不相等。

const over = Symbol();

const isOver = function (_over) {
  return _over === over;
}

生成函數 range

range 函數接受一個起始和終止參數,返回一個求值函數,運行求值函數返回一個值,終止的時候返回終止值。

const range = function (from, to) {
  let i = from;
  return function () {
    if (i < to) {
      i++
      console.log('range\t', i);
      return i
    }
    return over;
  }
}

轉換函數 map

接受一個求值函數和處理函數,獲取求值函數 flow 中的數據,對數據進行處理,返回一個流。

const map = function (flow, transform) {
  return function () {
    const data = flow();
    console.log('map\t', data);
    return isOver(data) ? data : transform(data);
  }
}

過濾函數 filter

接受一個求值函數,對求值函數 flow 中數據進行過濾,找到符合的數據并且返回。

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;
      }
    }
  }
}

中斷函數 stop

接受一個求值函數,當達到某個條件時中斷,可以用閉包函數加上 stop 函數接著實現一個 take 函數。

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;
  });
}

收集函數 join

因為返回的都是一個函數,最后得使用一個 join 函數來收集所有的值并且返回一個數組。

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

更優雅的實現

上面使用 函數 + 閉包 實現了惰性求值,但是還是不夠優雅,絕大部分代碼都放到迭代和判斷求值是否完成上面去了。其實 es6 中還有更好方法來實現惰性求值,就是使用 generator,generator 已經幫我們解決了迭代和判斷流是否完成,我們就可以專注于邏輯,寫出更簡潔易懂結構清晰的代碼。

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);
}

還得加上鏈式調用才算是完成了。

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

看完上述內容,你們對怎么在JavaScript中實現一個數組惰性求值庫有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女