手记

少侠,这次的内容炒冷饭了,函数Function。

少侠们好~

好久不见了,今天总算又和大家见面了。。。

正如你从标题里看见的,这次的内容是关于函数的,

虽然有点炒冷饭的嫌疑,

但是没办法,

毕竟函数是大多数少侠绕不过去的一道坎,

炒来炒去,

说不定熟了就绕过了。。。

好了,下面开始进入正题,

正文

首先,

这有一个简单的函数:

然后,现在少侠你有5秒时间从这个函数中拿到天辰dreamer。

5~

4~

3~

2~

1~

好了,时间到了,

下面是这次的答案:

嗯,这个答案简单得仿佛在侮辱少侠你的智商。。。

所以,

接下来我们要玩一个难度大些的,

从下面这个函数中拿到天辰dreamer:

这次少侠你有10秒时间来完成,

“。。。。。。真是无聊至极了”

好吧,这次的答案也很简单,

我们可以先调用一次two函数,

获取到里面的one函数,

然后再调用一次one函数,

获取到天辰dreamer:

或者我们也可以直接连续调用2次two函数,省略中间过程:

OK,

恭喜少侠你成功浪费掉了1分钟时间,

因为这2个例子确实有点废话的感觉,

但是!

在这个两个例子中,

确实也有一些有用的规则,

Rule1: 我们可以从一个函数中返回另外一个函数,当然,你也可以传递一个函数到另一个函数中。

Rule2: 返回的函数能获取到它定义时外层函数中的元素,即使是过后才调用

换成装逼点专业点的词汇就是高阶函数(Higher-order function)函数闭包(closure)。。。

没错,

就是那些被炒了无数遍,

随时随地都能看到相关文章,

到最后甚至看着就无聊的话题。。。


“那么既然这么无聊了,天辰你为什么还要说呢?”

“这么久没写文章,好不容易来一篇,就给我们看这个?”

“对啊对啊,对得起你100多个幽默风趣机智可爱的小粉丝吗?”

“。。。。。。。”


好吧,

主要是,

它们确实非常非常非常重要,

很多好玩的东西都需要在它基础之上才能完成。

还有就是暂时确实还没想好其他有趣的话题。。。

好了,

回到正式话题来,

在上面的基础上,我们有时候还会遇见一个问题,

那就是既然函数内部可以获取到外部函数的元素,

那么如果有多个同名的元素,到底应该获取哪一个呢?

比如下面这样:

又或者说,函数参数上也有叫做value的参数:

在这个函数中,有4个叫做value的元素,那么最终的value会获取哪一个呢?

正确答案是哪个最近就获取哪个

去掉one函数内部的value值:

别问我为什么,

别问我为什么不是哪个最远就获取哪个。

可能是因为它总得有个规则。

也可能是因为懒。。

这就是我们今天的第三条规则了:

Rule3: 当一个函数开始寻找某个元素时,它会从最内部开始依次向外部寻找,如果找到了多个相同名称的元素,它会采用最近的那一个。


好了,

现在少侠你已经掌握了3条关于函数的有趣的规则,

那他们有什么用呢?

第一个用处是可以帮助你在函数内部封装一些数据,

然后返回一个只具有特定功能的函数来操作它。

在这个例子中,

getArrayBy函数会根据你传递的字符串是even还是odd来返回nums中的偶数和奇数,或者默认返回nums的一份拷贝,

除此之外,没有其他任何方式能接触到nums本身,能够保证它的安全性和私密性,也可以防止被意外串改。

“哦,这样啊,朕知道了~”

“等一等!少侠,还有一个细节地方~”

既然少侠你已经知道了内部函数可以访问定义时外部函数中的元素,

那么我们把isOdd和isEven函数放在arrayMachine里面也许会更好一些,

反正在getArrayBy内部也能访问到~

不信?

不信的话可以照下面这样测试一下:

当然,也有更实用一些的例子,比如下面这个用来生成数据结构栈的函数:


怎么样?少侠。

还是挺有用的吧?

除了上面的情况之外,

另外比较有用的情况可能会是函数装饰器(function decorator)

或者说函数盒子,

比如下面这个once函数:

这个函数有什么用呢?

假如你有一个函数,出于某些情况,比如支付等等,

你想让这个函数只被调用一次,避免重复操作。

你就可以使用once函数处理它,经过once函数处理后的函数,只有第一次调用时有效。

once函数在内部保存了一个变量done,

返回了一个新函数decoratedFn,

在上面的例子就是onlySayHiOnce函数,

onlySayHiOnce在调用时会先判断once中的done是否为true,

如果已经为true了,就什么也不做,

否则,它才会调用之前传递进来的函数fn, 并把参数传给它,

同时它也会把once中的done设置为true,

这样以后调用时获取到的done总是为true, 就不会有任何效果了。

正如少侠你看见的,

once函数给我们原来的函数增加了一些功能,

就好像给装饰了一遍,所以通常这种函数也叫做函数装饰器,

不过,

那为什么又叫做函数盒子呢?

因为我觉得函数盒子听起来好玩一些,哈哈哈。。。


今天第二个有用的函数盒子可能是unary,

unary盒子会让你的函数变成只会接受一个参数的函数,

即使这个函数本来可以有多个参数:

unary函数能够解决下面这样的问题:

你可能期望结果是[1, 2, 3],但实际上不是。

造成这样的原因是系统内置的parseInt实际上可以接受一个数字作为第2个参数,

这个参数可以告诉你希望转换的进制:

然后。。。碰巧的是,数组自带的map,它会给你传递3个参数。。

当前元素,当前元素的索引,以及数组本身,

不好意思,你需不需要我不管,反正我就是要传3个参数!

然后就变成了。。。

要解决这个问题的话,你可以显示地手动只传递一个参数,

另外就是使用unary函数:

(哎呀,一不小心还解决了一道面试题,优秀~)

这个问题也告诉了我们一个问题,

一定要认真了解你正在使用的函数,

不要凭感觉哦,少侠~

“天辰,道理我都懂了,不过好像使用unary函数更麻烦一些,有什么意义呢?”

“毫无疑问,当然不是为了装逼~”


完全OK~

恭喜你,

少侠,

你又成功发现并阅读完了一篇文章,

按照惯例,

谢谢少侠你看到了这里,

然后~

希望少侠你能从中发现一些有趣的东西,

(或者人也行,比如机智的我)

当然,,

类似的函数盒子实际上还有很多,

不过不能一次性给放这里了,

因为可能是以后的素材。。。

“叮~ 从杂货店买到一本烂大街的closure技能书,已添加到储物袋里。”

“叮~ 发现两个奇怪的函数盒子,已添加到储物袋里。”

“叮~ 额外发现一个隐藏的封印的道具,栈(stack),栈。栈。。暂时不知道有什么用。。。”

(好奇怪的谐音梗。。。)



额外资源

自由变量(free variable)

不属于函数内部的变量叫做自由变量

纯函数(pure function)

不包含自由变量的函数叫做纯函数。

比如下面的one函数就是一个纯函数。

闭包函数(closure)

包含自由变量的函数叫做闭包函数。

下面two函数内部的one函数就是一个闭包函数


甩锅时间

少侠你可能会觉得比较奇怪的是,

为什么不直接解释闭包,作用域等等,而只是说了几个规则,

实际上,

不管是闭包,或是作用域等的,都只是某种语言规则,

有时候太纠结名称可能反而不好,

重要的是明白它们到底是在做什么。

比如少侠你可以说上面的规则是关于闭包和作用域,

或者你也可以换个角度,

说上面的只是关于如何在函数内部获取到一个值,

when, where, how,以及why。

why呢?

这里确实没有why,

因为why需要留给少侠你自己去思考~


你可能关心的问题

1、明说了,没看懂,怎么办?

少侠,不要在一棵树上吊死。。。

多看看不同的文章,综合归纳,做到举一反三,

不过,记得只给我点赞就行了。。哈哈。

2、再问一遍,为什么代码要用图片呢?

第一,好看,

第二,我自己做的,

第三,我自己做的,然后我又觉得很好看。

第四,你们手机上滑来滑去看代码不觉得麻烦?还不如图片放大看方便。


好了,溜了溜了~

少侠,江湖路上,有缘再见~

4人推荐
随时随地看视频
慕课网APP

热门评论

?100多小粉丝不在这,从掘金复制过来的。。。

查看全部评论