首頁 > web前端 > js教程 > 使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

PHP中文网
發布: 2016-05-16 15:37:31
原創
1108 人瀏覽過

程式設計範式

程式設計範式是一個由思考問題以及實現問題願景的工具所組成的框架。很多現代語言都是聚範式(或多重範式): 他們支援很多不同的程式範式,像是物件導向,元程式設計,泛函,面向過程,等等。

使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

函數式程式設計範式

函數式程式設計就像氫燃料驅動的汽車-先進的未來派,但還沒有被廣泛推廣。與命令式程式設計相反,他由一系列語句組成,這些語句用於更新執行時的全域狀態。函數式程式設計將計算轉換作表達式求值。這些表達式全由純數學函數組成,這些函數都是一流的(可以被當做一般值來運用和處理),並且沒有副作用。

使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

函數式程式設計很重視以下值:

函數是一等要務

我們應該將函數與程式語言中的其他類別物件同樣對待。換句話說,您可以將函數儲存在變數裡,動態建立函數,以及將函數傳回或將函數傳遞給其他函數。下面我們來看一個例子...

使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

一個字串可以保存為一個變數,函數也可以,例如:


var sayHello = function() { return “Hello” };
登入後複製

一個字串可以儲存為物件字段,函數也可以,例如:

var person = {message: “Hello”, sayHello: function() { return “Hello” }};
登入後複製

一個字串可以再用到時才創建,函數也可以,例如:

“Hello ” + (function() { return “World” })(); //=> Hello World
登入後複製

一個字串可以作為輸入參數傳給函數,則函數也可以:

    function hellloWorld(hello, world) { return hello + world() }
登入後複製

一個字串可以作為函數傳回值,函數也可以,例如:

return “Hello”;
return function() { return “Hello”};
登入後複製

高階案例

使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

如果函數將其他函數函數作為輸入參數或作為回傳值,則稱之為高階函數。剛才我們已經看過了一個高階函數的例子。下面,我們來看看更複雜的情況。

例1

[1, 2, 3].forEach(alert);
// alert 弹窗显示“1" 
// alert 弹窗显示 "2" 
// alert 弹窗显示 "3”
登入後複製

例2

function splat(fun) {
   return function(array) {
        return fun.apply(null, array);
   };
}
var addArrayElements = splat(function(x, y) { return x + y });
addArrayElements([1, 2]);
//=> 3
登入後複製

最愛純函數


Pure Functions


<純函數不會有其他的副作用,所謂的副作用指的是函數所產生的函數外界狀態的修改。例如:
  • 修改某個變數
  • 修改某個資料結構
  • 修改資料結構
  • 對外界對外部變數設定欄位

拋出例外或彈出錯誤訊息


最簡單的例子就是數學函數。 Math.sqrt(4) 函數總是傳回2。他不會用到任何其他心寒訊息,如狀態或設定參數。數學函數從來不會造成任何副作用。

Pure functions cannot mutate data

避免修改狀態




   var s = "HelloWorld";
    s.toUpperCase();
    //=> "HELLOWORLD"
    s;
    //=> "HelloWorld"
登入後複製
函數式程式設計支援純粹的函數,這樣的程式碼就不能改變資料,因此大多用於創建不可改變的數據。這種方式,不用修改一個已存在的資料結構,而且能高效的新建一個.

你也許想知道,如果一個純粹的函數通過改變一些本地數據而生產一個不可改變的返回值,是否是允許的?答案是可以。

在JavaScript中極少的資料型別是預設是不可改變的。 String是一個無法改變的資料類型的例子:




不可改變狀態的好處

    •    避免混亂和增加程序的準確性:在複雜系統內,大多數難以理解的Bug是由於狀態透過在程式中外部客戶端程式碼修改而導致的。

    •    確立「快速簡潔」的多執行緒程式設計:如果多執行緒可以修改同一個共享值,你必須同步的獲取值。這對專家來說都是十分乏味且易出錯的程式設計挑戰。 軟體事務記憶體和Actor模型提供了直接在線程安全方式下處理修改。

使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

使用遞歸而非循環呼叫

<🎜><🎜><🎜><🎜>遞歸是最有名的函數式程式設計技術。如果您還不知道它的話,那麼可以理解為遞歸函數就是一個可以呼叫自己的函數。 <🎜>

替代反复循环的最经典方式就是使用递归,即每次完成函数体操作之后,再继续执行集合里的下一项,直到满足结束条件。递归还天生符合某些算法实现,比如遍历树形结构(每个树枝都是一颗小树)。

在任何语言里,递归都是一项重要的函数式编程方式。很多函数语言甚至要求的更加严格:只支持递归遍历,而不支持显式的循环遍历。这需要语言必须保证消除了尾端调用,这是 JavasSrip 不支持的。

惰性求值优于激进计算

使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

数学定义了很多无穷集合,比如自然数(所有的正整数)。他们都是符号表示。任意特定有限的子集都在需要时求值。我们将其称之为惰性求值(也叫做非严格求值,或者按需调用,延迟执行)。及早求值会强迫我们表示出所有无穷数据,而这显然是不可能的。

很多语言都默认是惰性的,有些也提供了惰性数据结构以表达无穷集合,并在需要时对自己进行精确计算。

很明显一行代码 result = compute() 所表达的是将 compute() 的返回结果赋值给 result。但是 result 的值究竟是多少只有其被用到的时候才有意义。

可见策略的选择会在很大程度上提高性能,特别是当用在链式处理或者数组处理的时候。这些都是函数式程序员所喜爱的编程技术。

这就开创可很多可能性,包括并发执行,并行技术以及合成。

但是,有一个问题,JavaScrip 并不对自身进行惰性求值。话虽如此,Javascript 里的函数库可以有效地模拟惰性求值。

闭包的全部好处

所有的函数式语言都有闭包,然而这个语言特性经常被讨论得很神秘。闭包是一个函数,这个函数有着对内部引用的所有变量的隐式绑定。换句话说,该函数对它引用的变量封闭了一个上下文。JavaScript 中的闭包是能够访问父级作用域的函数,即使父级函数已经调用完毕。

   function multiplier(factor) {
      return function(number) {
          return number * factor;
      };
   }
  var twiceOf = multiplier(2);
    console.log(twiceOf(6));
//=> 12
登入後複製

声明式优于命令式编程

函数式编程是声明式的,就像数学运算,属性和关系是定义好的。运行时知道怎么计算最终结果。阶乘函数的定义提供了一个例子:

factorial(n) = 1 if n = 1

n * factorial(n-1) if n > 1

该定义将 factorial(n) 的值关联到 factorial(n-1),是递归定义。特殊情况下的 factorial(1) 终止了递归。

var imperativeFactorial = function(n) {
    if(n == 1) {
        return 1
    } else {
        product = 1;
        for(i = 1; i <= n; i++) {
              product *= i;
        }
        return product;
     }
}
var declarativeFactorial = function(n) {
       if(n == 1) {
             return 1
       } else {
             return n * factorial(n - 1);
      }
  }
登入後複製

从它实现阶乘计算来看,声明式的阶乘可能看起来像“命令式”的,但它的结构更像声明式的。

命令式阶乘使用可变值、循环计数器和结果来累加计算后的结果。这个方法显式地实现了特定的算法。不像声明式版本,这种方法有许多可变步骤,导致它更难理解,也更难避免 bug 。

使用 JavaScript 進行函數式程式設計 (一) 翻譯_javascript技巧

函数式JavaScript库

有很多函数式库:underscore.js, lodash,Fantasy Land, Functional.js, Bilby.js, fn.js, Wu.js, Lazy.js, Bacon.js, sloth.js, stream.js, Sugar, Folktale, RxJs 等等。

函数式程序员工具包

map(), filter(), 和 reduce()函数 构成了函数式程序员工具包的核心。 纯高阶函数成了函数式方法的主力。事实上,它们是纯函数和高阶函数应该仿效的典型。它们用一个函数作为输入,返回没有副作用的输出。

这些 JavaScript 函数对每一个函数式程序来说都是至关重要的。他们可以去除循环和语句,使得代码更加整洁。这些都是实现 ECMAScript5.1 的浏览器的标准,他们只处理数组。每次调用都会创建创建并返回一个新的数组。已存在的数组不会被修改。但是稍等,事情很不止于此。。。他们还将函数作为输入参数,通常是作为回调的匿名函数。他们会遍历将整个数组并且将该回调函数应用与每一项!

myArray = [1,2,3,4];

newArray = myArray.map(function(x) {return x*2});

console.log(myArray); // Output: [1,2,3,4]

console.log(newArray); // Output: [2,4,6,8]

除了这三个函数,还有很多函数可以扎入到几乎每一个函数式应用里:

forEach(),concat(), reverse(), sort(), every() 以及some().

JavaScript的範式

JavaScript當然不是嚴格意義上的函數式程式語言,這也促使了對其他範式的使用:

  • 命令式程式設計:基於詳細操作描述式的程式設計

  • 基於原型的物件導向式程式設計:基於原型物件及其實例的程式設計

  • 元程式程式設計:操縱JavsScript執行模型的程式設計方式。對元程式程式設計的一個很好的定義描述為「程式設計發生在您書寫程式碼做某事的時候,而元程式程式設計則發生在您書寫程式碼導致某事的解釋方式發生變化的時候。

以上就是使用JavaScript 進行函數式程式設計(一) 翻譯_javascript技巧的內容,更多相關內容請關注PHP中文網(www.php.cn)! 🎜>

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板