日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

RxJS Functional Programming

發布時間:2024/1/17 javascript 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 RxJS Functional Programming 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是函數式編程

簡單說,"函數式編程"是一種 "編程范式"(programming paradigm),也就是如何編寫程序的方法論。

它屬于 "結構化編程" 的一種,主要思想是把運算過程盡量寫成一系列嵌套的函數調用。舉例來說,現在有這樣一個數學表達式:

(5+6) - 1 * 3

傳統的過程式編程,可能這樣寫:

var a = 5 + 6; var b = 1 * 3; var c = a - b;

函數式編程要求使用函數,我們可以把運算定義成不同的函數:

const add = (a, b) => a + b; const mul = (a, b) => a * b; const sub = (a,b) => a - b;sub(add(5,6), mul(1,3));

我們把每個運算包成一個個不同的函數,并且根據這些函數組合出我們要的結果,這就是最簡單的函數式編程。

函數式編程基礎條件

函數為一等公民 (First Class)

所謂 "一等公民"(first class),指的是函數與其他數據類型一樣,處于平等地位,可以賦值給其他變量,也可以作為參數,傳入另一個函數,或者作為其它函數的返回值。

函數賦值給變量:

const greet = function(msg) { console.log(`Hello ${msg}`); } greet('Semlinker'); // Output: 'Hello Semlinker'

函數作為參數:

const logger = function(msg) { console.log(`Hello ${msg}`); }; const greet = function(msg, print) { print(msg); }; greet('Semlinker', logger);

函數作為返回值:

const a = function(a) {return function(b) {return a + b;}; }; const add5 = a(5); add5(10); // Output: 15

函數式編程重要特性

只用表達式,不用語句

"表達式"(expression)是一個單純的運算過程,總是有返回值;"語句"(statement)是執行某種操作,沒有返回值。函數式編程要求,只使用表達式,不使用語句。也就是說,每一步都是單純的運算,而且都有返回值。

原因是函數式編程的開發動機,一開始就是為了處理運算(computation),不考慮系統的讀寫(I/O)。"語句"屬于對系統的讀寫操作,所以就被排斥在外。

Pure Function

Pure Function (純函數) 的特點:

  • 給定相同的輸入參數,總是返回相同的結果

  • 沒有產生任何副作用

  • 沒有依賴外部變量的值

所謂 "副作用")(side effect),是指函數內做了與本身運算無關的事,比如修改某個全局變量的值,或發送 HTTP 請求,甚至函數體內執行 console.log 都算是副作用。函數式編程強調函數不能有副作用,也就是函數要保持純粹,只執行相關運算并返回值,沒有其他額外的行為。

前端中常見的產生副作用的場景:

  • 發送 HTTP 請求

  • 函數內調用 logger 函數,如 console.log、console.dir 等

  • 修改外部變量的值

  • 函數內執行 DOM 操作

接下來我們看一下純函數與非純函數的具體示例:

純函數示例:

const double = (number) => number * 2; double(5);

非純函數示例:

Math.random(); // => 0.3384159509502669 Math.random(); // => 0.9498302571942787 Math.random(); // => 0.9860841663478281

不修改狀態 - 利用參數保存狀態

函數式編程只是返回新的值,不修改系統變量。因此,不修改變量,也是它的一個重要特點。

在其他類型的語言中,變量往往用來保存"狀態"(state)。不修改變量,意味著狀態不能保存在變量中。函數式編程使用參數保存狀態,最好的例子就是遞歸,具體示例如下:

function findIndex(arr, predicate, start = 0) {if (0 <= start && start < arr.length) {if (predicate(arr[start])) {return start;}return findIndex(arr, predicate, start+1);} } findIndex(['a', 'b'], x => x === 'b'); // 查找數組中'b'的索引值

示例中的 findIndex 函數用于查找數組中某個元素的索引值,我們通過 start 參數來保存當前的索引值,這就是利用參數保存狀態。

引用透明

引用透明(Referential transparency),指的是函數的運行不依賴于外部變量或 "狀態",只依賴于輸入的參數,任何時候只要參數相同,引用函數所得到的返回值總是相同的。

非引用透明的示例:

const FIVE = 5; const addFive = (num) => num + FIVE; addFive(10);

函數式編程的優勢

1.代碼簡潔,開發快速

函數式編程大量使用函數,減少了代碼的重復,因此程序比較短,開發速度較快。

2.接近自然語言,易于理解,可讀性高

函數式編程的自由度很高,可以寫出很接近自然語言的代碼。我們可以通過一系列的函數,封裝數據的處理過程,代碼會變得非常簡潔且可讀性高,具體參考以下示例:

[1,2,3,4,5].map(x => x * 2).filter(x => x > 5).reduce((p,n) => p + n);

3.可維護性高、方便代碼管理

函數式編程不依賴、也不會改變外界的狀態,只要給定輸入參數,返回的結果必定相同。因此,每一個函數都可以被看做獨立單元,很有利于進行單元測試(unit testing)和除錯(debugging),以及模塊化組合。

4.易于"并發編程"

函數式編程不需要考慮"死鎖"(deadlock),因為它不修改變量,所以根本不存在"鎖"線程的問題。不必擔心一個線程的數據,被另一個線程修改,所以可以很放心地把工作分攤到多個線程,部署"并發編程"(concurrency)。

函數式編程中常用方法

forEach

在 ES 5 版本之前,我們只能通過 for 循環遍歷數組:

var heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; for (var i =0, len = heroes.length; i < len; i++) {console.log(heroes[i]); }

在 ES 5 版本之后,我們可以使用 forEach 方法,實現上面的功能:

forEach 方法簽名:

array.forEach(callback[, thisArg])

參數說明:

  • callback - 對數組中每一項,進行處理的函數

    • currentValue - 數組中正在處理的當前元素

    • index - 數組中正在處理的當前元素的索引

    • array - 處理的數組

  • thisArg (可選的) - 設置執行 callback 函數時,this 的值

以上示例 forEach 方法實現:

var heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; heroes.forEach(name => console.log(name));

map

在 ES 5 版本之前,對于上面的示例,如果我們想給每個英雄的名字添加一個前綴,但不改變原來的數組,我們可以這樣實現:

var heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; var prefixedHeroes = []; for (var i =0, len = heroes.length; i < len; i++) {prefixedHeroes.push('Super_' + heroes[i]); }

在 ES 5 版本之后,我們可以使用 map 方法,方便地實現上面的功能。

map 方法簽名:

const new_array = arr.map(callback[, thisArg])

參數說明:

  • callback - 對數組中每一項,進行映射處理的函數

    • currentValue - 數組中正在處理的當前元素

    • index - 數組中正在處理的當前元素的索引

    • array - 處理的數組

  • thisArg (可選的) - 設置執行 callback 函數時,this 的值

以上示例 map 方法實現:

var heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; var prefixedHeroes = heroes.map(name => 'Super_' + name);

filter

在 ES 5 版本之前,對于 heroes 數組,我們想獲取名字中包含 m 字母的英雄,我們可以這樣實現:

var heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; var filterHeroes = []; for (var i =0, len = heroes.length; i < len; i++) {if(/m/i.test(heroes[i])) {filterHeroes.push(heroes[i]);} }

在 ES 5 版本之后,我們可以使用 filter 方法,方便地實現上面的功能。

filter 方法簽名:

var new_array = arr.filter(callback[, thisArg])

參數說明:

  • callback - 用來測試數組的每個元素的函數。調用時使用參數 (element, index, array)。返回true表示保留該元素(通過測試),false則不保留。

  • thisArg (可選的) - 設置執行 callback 函數時,this 的值

以上示例 filter 方法實現:

var heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; var filterRe = /m/i; var filterHeroes = heroes.filter(name => filterRe.test(name));

參考資源

  • 函數式編程初探

  • 30天精通RxJS(02) 函數式編程基本概念

總結

以上是生活随笔為你收集整理的RxJS Functional Programming的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。