Notes

1、高阶函数的概念:Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.

2、自己yy的高阶函数优势:

  • 更少的代码。有效减少键盘磨损
  • 传统编程是复用对象、方法,高阶函数则是复用一种更加抽象的模式
  • 对于理解、熟练运用高阶函数的人而言,采用高阶函数比传统代码有更好的可读性

高阶函数是函数式编程的一种特性,当然js并不是函数编程语言,对于函数式编程可以参考——什么是函数式编程思维? - 用心阁的回答

3、代码收集:

① 高阶函数示例1

function greaterThan(n) {
return m => m > n;
}
let greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));
// → true

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

② 高阶函数示例2

function noisy(f) {
return (...args) => {
console.log("calling with", args);
let result = f(...args);
console.log("called with", args, ", returned", result);
return result;
};
}
noisy(Math.min)(3, 2, 1);
// → calling with [3, 2, 1]
// → called with [3, 2, 1] , returned 1

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

③ 高阶函数示例3

function unless(test, then) {
if (!test) then();
} repeat(3, n => {
unless(n % 2 == 1, () => {
console.log(n, "is even");
});
});
// → 0 is even
// → 2 is even

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

④ 高阶函数forEach,功能类似于for/of循环。

["A", "B"].forEach(l => console.log(l));
// → A
// → B

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

⑤ 用于过滤数据的高阶函数

function filter(array, test) {
let passed = [];
for (let element of array) {
if (test(element)) {
passed.push(element);
}
}
return passed;
} console.log(filter(SCRIPTS, script => script.living));
// → [{name: "Adlam", …}, …]

标准数组方法:

console.log(SCRIPTS.filter(s => s.direction == "ttb"));
// → [{name: "Mongolian", …}, …]

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

⑥ filter会生成过滤掉一些数据的新数组,map则从原有的数组构造一个长度相同、但数据经过转化的新数组。

function map(array, transform) {
let mapped = [];
for (let element of array) {
mapped.push(transform(element));
}
return mapped;
} let rtlScripts = SCRIPTS.filter(s => s.direction == "rtl");
console.log(map(rtlScripts, s => s.name));
// → ["Adlam", "Arabic", "Imperial Aramaic", …]

map同样是一个标准的数组方法。

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

⑦ 高阶函数reduce(或者说fold):通过对数组中的元素逐个进行某种累加运算产出一个结果。例如说求和sum(array),翻译成高阶函数就是reduce(array, (a, b) => a + b, 0)

function reduce(array, combine, start) {
let current = start;
for (let element of array) {
current = combine(current, element);
}
return current;
} console.log(reduce([1, 2, 3, 4], (a, b) => a + b, 0));
// → 10

标准数组方法:

console.log([1, 2, 3, 4].reduce((a, b) => a + b));
// → 10

reduce用于比较最后得出一个结果:

function characterCount(script) {
return script.ranges.reduce((count, [from, to]) => {
return count + (to - from);
}, 0);
} console.log(SCRIPTS.reduce((a, b) => {
return characterCount(a) < characterCount(b) ? b : a;
}));
// → {name: "Han", …}

更简单的例子:

[1, 23, 21, 12, 3, 5].reduce((a, b) => a > b ? a : b);
// → 23
[1, 23, 21, 12, 3, 5].reduce((a, b) => {
console.log(`compare ${a} with ${b}`);
return a > b ? a : b;
});
// → compare 1 with 23
// → compare 23 with 21
// → compare 23 with 12
// → compare 23 with 3
// → compare 23 with 5
// → 23

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

⑧ 高阶函数some

[2, 3, 2, 1, 2, 5, 7].some(a => a > 7);
// → false [2, 3, 2, 1, 2, 5, 7].some(a => a >= 7);
// → true [2, 3, 2, 1, 2, 5, 7].some(a => {
console.log(`start testing ${a}`);
return a == 1;
});
// → start testing 2
// → start testing 3
// → start testing 2
// → start testing 1
// → true

测试数组中的元素,只要其中任何一个满足就返回true

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

⑨ 高阶函数findIndex

[2, 3, 2, 1, 2, 5, 7].findIndex(a => a > 7);
// → -1 [2, 3, 2, 1, 2, 5, 7].findIndex(a => a >= 7);
// → 6 [2, 3, 2, 1, 2, 5, 7].findIndex(a => {
console.log(`start testing ${a}`);
return a == 1;
});
// → start testing 2
// → start testing 3
// → start testing 2
// → start testing 1
// → 3

4、重写课本示例代码(统计文本中字符的脚本归属分布)

数据:http://eloquentjavascript.net/code/scripts.js

数据格式:

  {
name: "Adlam",
ranges: [[125184, 125259], [125264, 125274], [125278, 125280]],
direction: "rtl",
year: 1987,
living: true,
link: "https://en.wikipedia.org/wiki/Fula_alphabets#Adlam_alphabet"
}

主代码:

/**
* 字符是由各种字符脚本处理的
* 通过每个字符的编码可以找到该字符的脚本归属
* 例如编码为1~100的字符由a脚本处理
* 编码为300~400、500~700的由b脚本处理
*/ /**
* 课本上的函数一般直接用“代表返回值的名词”做函数名
* 而java中这种情况一般用“get+代表返回值的名词”做函数名
* 如果觉得某个函数意义模糊,可以自行在函数前面脑补动词
*/ const textToCodes = (text) => {
let result = [];
for (let char of text) {
result.push(char.codePointAt(0));
}
return result;
}; const codeToScriptName = (code) => {
let result = null;
for (let script of SCRIPTS) {
if (script.ranges.some(([from, to]) => {
return code >= from && code < to;
})) {
result = script.name;
break;
}
}
return result;
}; const elementCounts = (arr) => {
let result = [];
for (let element of arr) {
let index = result.findIndex(a => a.label == element);
if (index == -1) {
result.push({label: element, count: 1});
} else {
result[index].count++;
}
}
return result;
}; const scriptsRate = (text) => {
let scriptNames = textToCodes(text).map(code => codeToScriptName(code));
let total = scriptNames.length;
let scriptCounts = elementCounts(scriptNames);
return scriptCounts.map(({label, count}) => {
return {
label: label == null ? "none" : label,
rate: (count / total).toFixed(2)
};
});
}; const main = () => {
let text = '英国的狗说"woof", 俄罗斯的狗说"тяв"';
console.log(scriptsRate(text).map(item => {
return `${item.rate * 100}% ${item.label}`;
}).join(", "));
}; main();
// → 46% Han, 25% none, 17% Latin, 13% Cyrillic

Exercises

① Flattening

let arrays = [[1, 2, 3], [4, 5], [6]];

arrays.reduce((sum, x) => {
console.log(`concat ${sum} and ${x}`);
return sum.concat(x);
});
// → concat 1,2,3 and 4,5
// → concat 1,2,3,4,5 and 6
// → [1, 2, 3, 4, 5, 6]

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

② Your own loop

const loop = (initVal, test, update, body) => {
let count = 0;
for (let i = initVal; test(i); i = update(i)) {
body(i);
}
}; loop(3, n => n > 0, n => n - 1, console.log);
// → 3
// → 2
// → 1

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

③ Everything

版本1:

function every(array, test) {
for (let x of array) {
if (!test(x)) return false;
}
return true;
} console.log(every([1, 3, 5], n => n < 10));
// → true
console.log(every([2, 4, 16], n => n < 10));
// → false
console.log(every([], n => n < 10));
// → true

版本2:

function every(array, test) {
return !array.some(x => !test(x));
} console.log(every([1, 3, 5], n => n < 10));
// → true
console.log(every([2, 4, 16], n => n < 10));
// → false
console.log(every([], n => n < 10));
// → true

--- --  ------------ - - - -- - -- - - - - - --- - - -             ----     -- --

④ Dominant writing direction

PS. 要用到示例代码中的数据。

const textToCodes = (text) => {
let result = [];
for (let char of text) {
result.push(char.codePointAt(0));
}
return result;
}; const codeToDirection = (code) => {
let result = null;
for (let script of SCRIPTS) {
if (script.ranges.some(([from, to]) => {
return code >= from && code < to;
})) {
result = script.direction;
break;
}
}
return result;
}; const elementCounts = (arr) => {
let result = [];
for (let element of arr) {
let index = result.findIndex(a => a.label == element);
if (index == -1) {
result.push({label: element, count: 1});
} else {
result[index].count++;
}
}
return result;
}; function dominantDirection(text) {
let derections = textToCodes(text).map(code => codeToDirection(code));
let derectionCounts = elementCounts(derections).filter(x => x.label != null);
return derectionCounts.reduce((a, b) => {
return a.count > b.count ? a : b;
}).label;
} console.log(dominantDirection("Hello!"));
// → ltr
console.log(dominantDirection("Hey, مساء الخير"));
// → rtl

Eloquent JavaScript #05# higher-order functions的更多相关文章

  1. [CS61A] Lecture 5&6&7. Environments & Design & Functions Examples & Homework 2: Higher Order Functions

    [CS61A] Lecture 5&6&7. Environments & Design & Functions Examples & Homework 2: ...

  2. 46 Simple Python Exercises-Higher order functions and list comprehensions

    26. Using the higher order function reduce(), write a function max_in_list() that takes a list of nu ...

  3. [React] Higher Order Components (replaces Mixins)

    Higher order components will allow you to apply behaviors to multiple React components. So the idea ...

  4. Eloquent JavaScript #13# HTTP and Forms

    索引 Notes fetch form focus Disabled fields form’s elements property 阻止提交 快速插入单词 实时统计字数 监听checkbox和rad ...

  5. [React] Implement a Higher Order Component with Render Props

    When making a reusable component, you'll find that people often like to have the API they're most fa ...

  6. [Redux] Understand Redux Higher Order Reducers

    Higher Order Reducers are simple reducer factories, that take a reducer as an argument and return a ...

  7. [React Intl] Use a react-intl Higher Order Component to format messages

    In some cases, you might need to pass a string from your intl messages.js file as a prop to a compon ...

  8. [React] Cleanly Map Over A Stateless Functional Component with a Higher Order Component

    In this lesson we'll create a Higher Order Component (HOC) that takes care of the key property that ...

  9. Eloquent JavaScript #03# functions

    索引: let VS. var 定义函数的几种方式 more... 1.作者反复用的side effect side effect就是对世界造成的改变,例如说打印某些东西到屏幕,或者以某种方式改变机器 ...

随机推荐

  1. (转)Redis集群搭建与简单使用(最少需要 6个节点)

    介绍安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟机都是 CentOS ,一台 ...

  2. eclipse中安装maven,配置本地仓库和镜像

    1.安装maven,配置MAVEN_HOME 首先:下载免安装版解压配置MAVEN_HOME(和配置JAVA_HOME一样) 然后按照下面的配置,主要第3步,指定settings.xml文件的位置(在 ...

  3. Elasticsearch5.x批量插入数据(Java)

    先上官方示例代码:官方示例 Java代码: // 批量插入数据 public void InsertBatch() { try { // 设置集群名称 Settings settings = Sett ...

  4. python math random

    很有用个的工具 值得好好看看,这是作者(python发明者)对于工作中使用到的大多数场景的提炼 //test.py 1 import math 2 3 print abs(-10) 4 print m ...

  5. 安装FusionInsight

    1.在华为平台上下载整体客户端,不建议下载单个组件客户端,后期关联测试还是要装上的.   2.下载后需要将服务器上的客户端拷贝到本地.打开xShell,新建会话,登陆本地虚拟机上的Linux系统(19 ...

  6. C++ 执行 cmd 命令 删除文件 删除注册表项

    #include <Windows.h> WinExec("cmd /C \"del C:\\Windows\\secretWin.ini\"",S ...

  7. MyBatis基础入门《三》Select查询集合

    MyBatis基础入门<三>Select查询集合 描述: 代码新增了一个MybatisUtil工具类,查询数据库返回集合的时候,接收数据的三种方式.由于代码会渐渐增多,未涉及改动过的文件不 ...

  8. 解析img图片没找到onerror事件

    本篇文章主要介绍了img图片没找到onerror事件 Stack overflow at line: 0 需要的朋友可以过来参考下,希望对大家有所帮助 打开网页时提示 Stack overflow a ...

  9. idea软件上设置爱彼迎字体

  10. 水题B

    国际象棋的棋盘是黑白相间的8 * 8的方格,棋子放在格子中间.如下图所示: 王.后.车.象的走子规则如下: 王:横.直.斜都可以走,但每步限走一格. 后:横.直.斜都可以走,每步格数不受限制. 车:横 ...