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

2020-02-10  本文已影响0人  天辰dreamer
image

少侠们好~

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

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

虽然有点炒冷饭的嫌疑,

但是没办法,

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

炒来炒去,

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

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

正文

首先,

这有一个简单的函数:

image

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

5~

4~

3~

2~

1~

好了,时间到了,

下面是这次的答案:

image

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

所以,

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

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

image

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

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

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

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

获取到里面的one函数,

然后再调用一次one函数,

获取到天辰dreamer:

image

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

image

OK,

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

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

但是!

在这个两个例子中,

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

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

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

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

没错,

就是那些被炒了无数遍,

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

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


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

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

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

“。。。。。。。”


好吧,

主要是,

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

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

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

好了,

回到正式话题来,

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

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

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

比如下面这样:

image

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

image

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

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

image

去掉one函数内部的value值:

image

别问我为什么,

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

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

也可能是因为懒。。

image

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

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

image

好了,

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

那他们有什么用呢?

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

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

image

在这个例子中,

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

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

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

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

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

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

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

image

不信?

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

image

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

image

怎么样?少侠。

还是挺有用的吧?

除了上面的情况之外,

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

或者说函数盒子,

比如下面这个once函数:

image

这个函数有什么用呢?

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

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

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

image

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

返回了一个新函数decoratedFn,

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

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

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

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

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

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

正如少侠你看见的,

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

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

不过,

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

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


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

image

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

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

image

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

image

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

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

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

image

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

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

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

然后就变成了。。。

image

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

image

另外就是使用unary函数:

image

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

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

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

不要凭感觉哦,少侠~

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

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


完全OK~

恭喜你,

少侠,

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

按照惯例,

谢谢少侠你看到了这里,

然后~

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

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

当然,,

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

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

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

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

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

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

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

image
image

额外资源

自由变量(free variable)

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

image

纯函数(pure function)

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

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

image

闭包函数(closure)

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

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

image

甩锅时间

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

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

实际上,

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

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

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

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

或者你也可以换个角度,

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

when, where, how,以及why。

image

why呢?

这里确实没有why,

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


你可能关心的问题

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

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

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

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

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

第一,好看,

第二,我自己做的,

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

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


好了,溜了溜了~

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

image
上一篇下一篇

猜你喜欢

热点阅读