首頁 web前端 js教程 《JavaScript函數式程式設計》讀後感_javascript技巧

《JavaScript函數式程式設計》讀後感_javascript技巧

May 16, 2016 pm 03:46 PM

這篇文章記錄本人在學習 函數式 中理解到的一些東西,加深記憶和並且整理記錄下來,方便之後的複習。

在近期看到了《JavaScript函數式程式設計》這本書預售的時候就定了下來。主要目的是個人目前還是不理解什麼是函數式程式設計。在自己學習的過程中一直聽到身邊的人說面向過程編程和物件導向編程,而函數式就非常少。為了自己不要落後於其他同學的腳步,故想以寫筆記的方式去分享和記錄自己閱讀中所汲取的知識。

js 和函數式程式設計

書中用了一句簡單的話來回答了什麼是函數式程式設計:

函數式程式設計透過使用函數將值轉換為抽象單元,接著用於建構軟體系統。
我覺得一定有同學看了這一句還是不太動什麼是函數式編程,為什麼要用函數式編程。後面的很多例子都使用到Underscore了。

以函數為抽象單元

抽象方法是指隱藏了細節的函數。舉一個書中的例子,一個偵測輸出年齡值的函數(主要是關於錯誤和警告的報告):

function parseAge(age) {
  if (!_.isString(age))
    throw new Error("Expecting a string");
  var a;
  console.log("Attempting to parse an age");

  a = parseInt(age, 10);
  if (_.isNaN(a)) {
    console.log(["Could not parse age: "].join());
    a = 0;
  }

  return a;
}

登入後複製

上面的函數判斷我們是不是輸入一個年齡,而且必須是字串形式。接著就是來運行這個函數:

parseAge("42"); //=> 42
parseAge(42); //=> Error:Expecting a string
parseAge("hhhh"); //=> 0
登入後複製

上面的parseAge函數正常運作沒有什麼問題。如果我們要修改輸出錯誤=資訊和警告的呈現方式、那麼就需要修改對應的程式碼行,以及其他地方的輸出模式。書中給的方法是透過將它們抽象化成不同的函數來實現:

function fail(thing) {
  throw new Error(thing);
}

function warn(thing) {
  console.log(["WARNING:", thing].join(''));
}

function note(thing) {
  console.log(["NOTE:", thing].join(''));
}

登入後複製

接著就是使用上面的函數,去重構parseAge這個函數。

funciton parseAge(age) {
  if (!_.isString(age))
    fail("Expecting a string");
  var a;

  note("Attempting to parse an age");
  a = parseInt(age, 10);

  if (_.isNaN(a)) {
    warn(["Could not parse age:", age].join(""));
    a = 0;
  }

  return a;
}

登入後複製

把報告錯誤的程式碼都放到不同的函數裡去,且重構後的parseAge和之前的也沒有多大的變化。但是不同的就是現在報告錯誤、資訊和警告的想法已經被抽象化。錯誤、資訊和警告的報告結果也是完全被修改了。

這麼做是,由於行為包含在單一的函數中,所以函數可以被能夠提供類似行為的新函數取代,或直接被完全不同的行為取代。

封裝與隱藏

這個標題很容易理解,舉個例子。像我們經常使用iife來避免全局的污染,這就是一個封裝和隱蔽的很好例子。透過使用iife來隱藏自己的寫的一些變數和方法,目的就是不去污染全局的環境。這也是使用閉包的方式來隱藏資料。

因為閉包也是一種函數。且和現在在學習函數式程式設計有莫大的關係。但也不要忘記了之前學習的物件導向封裝,畢竟這兩者不能說誰更加的好。但是都掌握了也不是一件壞事。一句老話:看需求。

以函數為行為單位

隱藏資料和行為(通常不方便快速修改)只是一種講函數作為抽象單元的方式。另一種方式就是提供一種簡單地儲存方式和傳遞基本行為的離線散單元。

書中一個小栗子,透過使用js語法來索引數組中的一個值:

var arr = ['a', 'b', 'c'];
arr[1] //=> b
登入後複製

雖然上面索引數組中的中的一個值很簡單,但並沒有辦法可以在不把它放到函數裡的前提下,獲取這個行為並根據需要來使用他/她。寫一個簡單函數nth,用來索引數組中的一個值:

function nth(a, index) {
  return a[index];
}
登入後複製

接著運行:

nth(arr, 1); //=> b
運行成功,但是如果傳入一個空物件時,就會報錯了。因此,如果想圍繞nth來實現函數抽象,我們或許會設計下面的聲明:nth傳回一個儲存在允許索引存取的資料類型中的有效袁術。這段聲明的關鍵在於索引資料的類型的概念。或許需要一個函數來判斷類型:

function isIndexed(data) {
  return _.isArray(data) || _.isString(data);
}
登入後複製

接著繼續完善nth函數。 isIndexed函數是一個提供了判斷某個資料是否為字串或陣列的抽象。

function nth(a, index) {
  if (!_.isNumber(index)) 
    fail("Expected a number as the index");
  if (!isIndexed(a))
    fail("Not supported on non-indexed type");
  if ((index < 0) || (index > a.length - 1))
    fail("Index value is out of bounds");

  return a[index];
}

登入後複製

從index抽物件建構nth函數抽象的方式一樣,也可以用同樣的方式來建構一個second抽象:

function second(a) {
  return nth(a, 1);
}
登入後複製

函数second允许在一个不同但相关的情况下,正确的使用nth函数:

second(arr); //=> b
通过上面的栗子,就知道。我们可以把每一步都抽象成一个函数,把每一个参数都抽象出来。虽然这样写感觉定义了许多函数。不过这样更加容易理解每一项的功能和流程。

数据抽象

JavaScript 的对象原型模型是一个丰富且基础的数据方案。
因为js没有类的原因,就有了许多模拟类的方法,且在ES6上也出现了class关键字。尽管类有许多长处,但很多的时候js应用程序的数据需求币类中的简单的要多。

基于类的对象系统的一个有理的论据是实现用户界面的历史使用。
js中的对象和数组已经能够满足我们对数据的操作了,且Underscore也是重点也是如何处理数组和对象。

实施和使用的简易性是使用js的核心数据结构进行数据建模的目的。这并不是说面向对象或者基于类的方法就完全没有用。处理集合为中心的函数式方式更加适合处理与人有关的数据,而面向对象的方法最适合模拟人。

js函数式初试

在开始函数式编程前,需要先定义两个常用且有用的函数:

function existy(x) {
  return x != null
}

function truthy(x) {
  return (x !== false) && existy(x);
}

登入後複製

existy函数旨在定义事物之前的存在。js中就有两个值可以表示不存在:null和undefined。
truthy函数用来判断一个对象是否应该认为是true的同义词。

我们可以在很多地方使用到这两个函数,其实函数式理念来自于它们的使用。有些同学可能已经熟悉了许多js实现中的map forEach等方法。且Underscroe也提供了许多类似的方法,这也许就是选择Underscroe来辅助学习函数式编程的原因。

简单说下就是:

一个对”存在“的抽象函数的定义。
一个建立在存在函数之上的,对”真“的抽象函数定义。
通过其他函数来使用上面的两个函数,以实现更多的行为。

加速

大概了解了函数式编程之后。你可能会想这函数式编程不是很慢吗?比如前面获取数组索引,有必要定义一个函数来专门获取吗?直接用arr[index]绝对比那些函数来的快。

var arr = [1, 2, 3, 4, 5];

// 最快
for (var i = 0; i < arr.length; i++) {
  console.log(arr[i]);
}

// 较慢
_.each(arr, function (val, index) {
  console.log(index);
});

登入後複製

但是我们在写代码的时候可能不会考虑的那么深,也许使用函数的确比原生要慢一些。但是大多数情况下也不会去在乎那么点时间,且现在有强大的v8引擎,大部分情况下的他都能很高效的编译和执行我们的js代码。所以我们没有必要在还没有写出正确的代码前考虑运算速度。

如果是我来选择的话,可能会更加关注与代码的风格。那种写法写的舒服看的舒服就使用哪一种,当然也是要保证基本的运算速度下,以不至于慢的离谱。看的舒服的代码比跑的快的代码可能更加有成就感。

总结

看完了第一章也是可以小结一下js的函数式编程。下面引用书上的总结:

确定抽象,并为其构建函数。
利用已有的函数来构建更加复杂的抽象。
通过将现有的函数传给其他的函数来构建更加复杂的抽象。
单是构建抽象还是不够的,如果能够把强大的数据抽象结合来实现函数式编程效果会更加好。

后面的章节读后感会慢慢的分享给大家,敬请关注。

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

前端熱敏紙小票打印遇到亂碼問題怎麼辦? 前端熱敏紙小票打印遇到亂碼問題怎麼辦? Apr 04, 2025 pm 02:42 PM

前端熱敏紙小票打印的常見問題與解決方案在前端開發中,小票打印是一個常見的需求。然而,很多開發者在實...

神秘的JavaScript:它的作用以及為什麼重要 神秘的JavaScript:它的作用以及為什麼重要 Apr 09, 2025 am 12:07 AM

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

誰得到更多的Python或JavaScript? 誰得到更多的Python或JavaScript? Apr 04, 2025 am 12:09 AM

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? 如何使用JavaScript將具有相同ID的數組元素合併到一個對像中? Apr 04, 2025 pm 05:09 PM

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

JavaScript難以學習嗎? JavaScript難以學習嗎? Apr 03, 2025 am 12:20 AM

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

如何實現視差滾動和元素動畫效果,像資生堂官網那樣?
或者:
怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? 如何實現視差滾動和元素動畫效果,像資生堂官網那樣? 或者: 怎樣才能像資生堂官網一樣,實現頁面滾動伴隨的動畫效果? Apr 04, 2025 pm 05:36 PM

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

console.log輸出結果差異:兩次調用為何不同? console.log輸出結果差異:兩次調用為何不同? Apr 04, 2025 pm 05:12 PM

深入探討console.log輸出差異的根源本文將分析一段代碼中console.log函數輸出結果的差異,並解釋其背後的原因。 �...

JavaScript的演變:當前的趨勢和未來前景 JavaScript的演變:當前的趨勢和未來前景 Apr 10, 2025 am 09:33 AM

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

See all articles