Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

写更简洁的代码 by 函数式编程 #17

Open
law-chain-hot opened this issue Apr 17, 2020 · 0 comments
Open

写更简洁的代码 by 函数式编程 #17

law-chain-hot opened this issue Apr 17, 2020 · 0 comments

Comments

@law-chain-hot
Copy link
Owner

law-chain-hot commented Apr 17, 2020

写更简洁的代码 by 函数式编程

本文代码引用自 https://dev.to/r0r71z/javascript-write-cleaner-code-with-functional-programming-279a
不得不说,Dev.to 是个我暂时发现的美术风格我很喜欢的前端社区

Although we could use code comments or JSDocs to explain what each line in this code is doing, we should rather think of leveraging the power of a functional programming language.

本文是 3 步走,看如何把下面这个千层饼嵌套的代码修改为函数式编程风格的代码

1. 原版

Click me!
var fetch = require('node-fetch'); // if using NodeJS

function articles () {
  var arr = [];
  return fetch('https://dev.to/api/articles').then(function(a) {
    if (a) {
      return a.json().then(function(b) {
        if (b) {
          b.forEach((c) => {
            if (c.tag_list.indexOf('javascript') !== -1 && c.tag_list.indexOf('node') !== -1) {
              arr.push(c);
            }
          });
          return arr;
        }
      });
    }
  });
}

articles().then(function(d) {
  console.log(d);
});
这是修改之前的代码,我承认我并没能在第一次读懂这个代码在干嘛 -。-

2. 改版

Click me again!
const arr = [];

function pushFilteredArticlesToAuxArray (c) {
  if (
    c.tag_list.indexOf('javascript') !== -1
    && c.tag_list.indexOf('node') !== -1
  ) {
    arr.push(c);
  }
}

function filterAndReturnValues (b) {
  if (b) {
    b.forEach(pushFilteredArticlesToAuxArray);
    return arr;
  }
}

function fetchJSDevArticles () {
  return fetch('https://dev.to/api/articles').then(function(a) {
    if (a) {
      return a.json().then(filterAndReturnValues);
    }
  });
}

fetchJSDevArticles().then(function(d) {
  console.log(d);
});
我承认,优雅了很多,有了规范的函数命名,并且拆解的每个步骤,就是所谓的 make code more composable, more readable

但是下面这个版本才是最终形态

3. 最终版

Click me again and again!
const fetch = require('node-fetch');

const tagsToFilter = ['javascript', 'node'];
const devArticlesApiURL = 'https://dev.to/api/articles';

const isIncludedIn = (arr) => tag => arr.includes(tag);
const byTags = (tags) => (article) => tags.every(isIncludedIn(article.tag_list));
const filterAndReturnValues = (articles) => articles.filter(byTags(tagsToFilter));

const fetchJSDevArticles = () =>
  fetch(devArticlesApiURL)
    .then(response => response.json())
    .then(filterAndReturnValues)
    .catch(console.log);

fetchJSDevArticles().then(console.log);

天,这真的是很优雅了

怎么样来理解呢,举个例子,我们看 byTags() 这个函数,变化为 ES5 就是

// ES6 arrow function
const byTags = (tags) => (article) => tags.every(isIncludedIn(article.tag_list));

// ES5 function
const byTags = function (tags) {
    return function (article) {
        return tags.every(isIncludedIn(article.tag_list);
    }
}

目的是:传入一个 tags 变量,被新返回的函数 function(article) 使用。而这个新返回的函数的 parameter 是从 filter 函数的参数的第一个参数(对不起,就是这样的绕) articles.filter(byTags(tagsToFilter)); ,所以就是 articles 中的每个 article

最后,再放一次看看修改前后的差别吧

// ====== 修改前,世界模糊 ======
var fetch = require('node-fetch'); // if using NodeJS

function articles () {
  var arr = [];
  return fetch('https://dev.to/api/articles').then(function(a) {
    if (a) {
      return a.json().then(function(b) {
        if (b) {
          b.forEach((c) => {
            if (c.tag_list.indexOf('javascript') !== -1 && c.tag_list.indexOf('node') !== -1) {
              arr.push(c);
            }
          });
          return arr;
        }
      });
    }
  });
}

articles().then(function(d) {
  console.log(d);
});
// ====== 修改后,世界明了 ======
const fetch = require('node-fetch');

const tagsToFilter = ['javascript', 'node'];
const devArticlesApiURL = 'https://dev.to/api/articles';

const isIncludedIn = (arr) => tag => arr.includes(tag);
const byTags = (tags) => (article) => tags.every(isIncludedIn(article.tag_list));
const filterAndReturnValues = (articles) => articles.filter(byTags(tagsToFilter));

const fetchJSDevArticles = () =>
  fetch(devArticlesApiURL)
    .then(response => response.json())
    .then(filterAndReturnValues)
    .catch(console.log);

fetchJSDevArticles().then(console.log);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant