6、高级函数
JavaScript的函数其实都指向某个变量。既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
function add(x, y, f) {
return f(x) + f(y);
}
编写高阶函数,就是让函数的参数能够接收别的函数。
6.1 map/reduce
map()方法定义在JavaScript的Array中,用于对数组中每个元素执行相应的操作。
var arr = [1,2,3,4,5];
function pow(x) {
return x * x;
};
var arr1 = arr.map(pow);
reduce()方法则有一种迭代的效果。
var arr = [1,2,3,4,5];
function add(x, y) {
return x + y;
};
arr.reduce(add);
// reduce 执行效果是 1+2+3+4+5 = 15
因此可以利用reduce进行求和/积,同时也可以将存在数组里面的数字转换成一个整数:
var arr = [1,2,3,4,5];
var num = arr.reduce(function toNumber(x,y){
return x * 10 + y;
});
// num 12345
6.2 filter
用于把Array的某些元素过滤掉,然后返回剩下的元素:
原理:filter的参数是一个函数,这个函数会接受三个参数:element,数组元素;index,元素的index;self,数组本身。之后filter会把每个element都放入函数里面进行一次判断,如果函数返回true,则代表element满足函数条件,不会被清洗掉,否则就被清洗掉了。
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r; // [1, 5, 9, 15]
用filter()这个高阶函数,关键在于正确实现一个“筛选”函数。
利用filter,可以巧妙地去除Array的重复元素。
var r = arr.filter((element, index, self) =>{
return self.indexOf(element) === index; // 元素出现的第一个位置是不是当前元素的位置
});
6.3 sort
对Array进行排序,但Array的排序会默认把所有元素转换成 string之后再排序,字母会使用首字母的ASCII码进行比较。
['Google', 'Apple', 'Microsoft'].sort(); // ['Apple', 'Google', 'Microsoft'];
['Google', 'apple', 'Microsoft'].sort(); // ['Google', 'Microsoft", 'apple']
[10, 20, 1, 2].sort(); // [1, 10, 2, 20];// 转换字符串后1在2的前面
不过sort()方法也是一个高阶函数,它还可以接收一个比较函数来实现自定义的排序。
var arr = [1,10,2,20];
arr.sort ( function (x, y) {
if (x > y){
return 1;
}else if (x < y){
return -1;
}
return 0;
});
arr; // [1,2,10,20]
sort()方法会直接对Array进行修改,它返回的结果仍是当前Array。
6.4 闭包
闭包:就是能够读取其他函数内部变量的函数,或者子函数在外调用,子函数所在的父函数的作用域不会被释放。
简单来讲,就是帮助解决全局变量过多造成污染的问题。
举个🌰:
var a = 1;
function Person(){
a++;
return a;
}
上面是一个自增的例子,但是a是个全局变量,这样子其他函数不小心用了 a 就会造成 a 的 value 被污染。因此便提出来闭包。
function Person(){
var a = 1;
function ruby(){
a++;
}
return ruby();
}
let rub = Person(); // ruby()
rub(); // 执行,此时会返回 2;
rub(); // 3;
很好理解,因为rub()函数就是ruby()函数,ruby函数勾连着a,那么Person函数里面的a就不会被释放
,反而会一直存在,就会造成一种全局变量的假象,但是是一个局部变量。
6.5 函数柯里化
函数柯里化是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术
。
简单来讲,便是最初一个函数接受很多个参数,但是现在通过函数里面设置函数来分别接受单个参数:
function(x,y);
function(x){
return function(y);
}
函数柯里化很适合用在闭包里面。
6.6 箭头函数
在ES6中提出了箭头函数,用于替代function这些复杂的文字,例如:
var a = function(a,b){
return a+b;
}
替换: 当然,主体还是要放在 {...} 中,只不过参数放在()里面,然后直接一个 =>来替换 function。
var a = (a,b) = > {
return a+b;
}
6.6.1 this
箭头函数在JS里面尤为重要:这里我们需要了解一下,在js里面,有一个全局环境,这个全局环境只有一个,就是window。
然后这里讲一下匿名函数,匿名函数就是没有名字:
var a = function() {
...
}
普通函数的函数内部环境就是当前函数的环境,当我们使用this时,this会自动绑定成函数所属的对象
。
var a = {
name = 'ruby',
getName(){
return this.name;
}
}
a.getName(); // ruby
但是匿名函数有个问题,就是函数环境自动转换成全局环境,说白了,就是在匿名函数里面使用this,this会绑定到window上
。
name = 'leo';
var b = {
name = 'ruby',
getName(){
return function(){
return this.name;
}
}
}
b.getName(); // leo
一般这个时候,最简单的方法就是找个变量来承接当前环境的this
:
name = 'leo';
var b = {
name = 'ruby',
getName(){
var that = this; // 这个this就指向b了
return function(){
return that.name;
}
}
}
b.getName(); // ruby
但是我既想使用匿名函数方便,又不想浪费内存存储变量,那么此时ES6就提出来箭头函数来解决匿名函数环境选择的问题。
箭头函数看上去是一种匿名函数的简写,但实际上,箭头函数和匿名函数有个明显的区别:箭头函数内部的this是词法作用域,也就是说,this不会去直接找全局变量,而是找当前函数所属的对象
,问题解决了😄
name = 'leo';
var b = {
name = 'ruby',
getName(){
return () => {
return this.name;
}
}
}
b.getName(); // ruby
本文来源廖雪峰老师教程的笔记,有疑惑可以直接访问廖雪峰老师教程:https://www.liaoxuefeng.com/wiki/1022910821149312/1023022043494624