0 1 5 8 ★ 小王子与Js教主 |【By-老刘】
本帖最后由 不二如是 于 2017-7-28 10:25 编辑推荐阅读:
0 1 5 7 ★ 寥寥数行代码玩透“hoist”|【高级玩家必看】
0 1 3 2 ★ 小心! 这里有'隐式的强制转换'!!! | 【握草,Boom~~~】
0 1 3 3 ★ 得“闭包”者得天下! | 【精英版】
登场人物名:
小兰 : lambda
邱大教主:阿隆佐.丘齐(Alonzo Church)Lambda演算发明人
[*] 拜函数教
Java 小王子在 JavaScript 王国待了也有一段时间了。
这里虽然不像 Java 帝国那样规范严苛,但也因此千奇百怪,五光十色。
要说小王子最喜欢待的地方,那还是人来人往的 JSON 酒馆,不仅有上好的酒菜,还有机会认识到各式各样的人。
这不,一来二去他已经和上回认识的眼镜官员成了朋友,甚至私底下还称兄道弟的。
这一天小王子又和眼镜大哥一起约来吃酒。
才寒暄了几句,筷子还没动,酒馆门口就发生了一点骚动。
只见来了一位看起来像是教书先生的精瘦男子,旁边还有些随从。
“...... 大哥,这人什么来头,气度不凡啊。”
小王子悄声向旁边的眼镜官员问到。
“哈哈,他是拜函数教的邱大教主,最近他们教派的信众激增啊,真是风水轮流转。”
“函数式?“
以前随父亲经商途中是听说过他们的事情,好像非常古老而且高深莫测啊。
据说只有学者和虔诚的教徒才会加入他们,怎么最近也接收新人了?
“小弟果然是见多识广,不错,在很久以前的确是这样,不过为何有大批新教徒这种事情也不在我的管辖范围内啊,所以也不太清楚。但是毕竟我是本国语言规范审查官,还是与他打过一些交道。不妨我们邀请他来一起喝酒,你亲自问他。”
小王子本来听到眼镜大哥也不了解情况正有些失望。
突然得知可以直接面对面打探对方的底细,顿时兴奋了起来。
“那太好了!”
“这不是眼镜老弟么,别来无恙啊。”
“主教兄,甚好甚好,要不这顿我请?小二!”
饭菜上桌,互相客套了几句之后,话题就开始了。
“主教兄,这是我最近认识的朋友,年纪轻轻就周游四方,他有些事情要问你。”
“哦?”函数式主教把目光放了过来,“有何见教?”
“久闻贵教派向来神秘,为何最近有如此多的新教徒加入呢?”
“哈,这个嘛 ... 现在的年轻人都不喜欢条条框框,本教向来以简洁强大著称,自然就受欢迎了。”
小王子心想,这个教主倒也是有话直说、自卖自夸。
不过难道没了面向对象这种强大的武器,他还能变出怎么样的花儿来?
“那还敢请教教主大人,依你看要怎么实现 Animal, Cat, Dog 这些对象呢?”
想了一会儿,小王子认为不如直接发问。
“这个嘛,本教派并无对象这种说法,不过如果你愿意,也可以构造一个对象出来,只需要......”
“我们拜函数教不用对象~”
还没等着主教说完,旁边的妹子突然发话了。
“哦,小兰,你来说吧。”
这位被叫做小兰的少女像是主教的助手,看起来深得主教信任。
“嘻嘻,教主大人说的太复杂了,其实实现你说的那些根本不用什么对象。”
“哦?那该怎么做?”
小王子顿时来了兴趣。
[*]一等公民:函数
“你想啊,搞出来这些猫啊狗啊的,不就是想让他们都可以吃东西么?干嘛要封装到一个对象中,太压抑了”
哦!
Java 小王子恍然大悟,在自己的Java帝国,法律非常严格, 类和对象才是一等公民。
函数是不可能独立存在的, 你即使是想输出一个简单的hello world , 也必须写一个类。
在类中写一个方法 , 在这个方法中才能输出hello world 。
在这里函数已经翻身做主人,成为了一等公民。
再也不用困在对象的牢笼中,声明后就可以直接使用。
“也就是说,猫、狗都可以直接拿来调用咯?”
“是的呢~ 不止是猫、狗,连人都能作为参数调用呢, 只要一个对象有name这个属性就行啊”
小兰的脸上还是一样的笑容。
长期在一个强类型的语言中生活,小王子对这种有点“变态”的灵活性还真不习惯。
他说:
“在Java帝国,方法的参数都有确定的类型,如果你的方法写错了,IDE就能自动帮你检测, 减少了很多错误,现在可就没这种福利了。”
“有得必有失嘛”
小兰笑道
“你可以多写一点单元测试来保证正确性啊”
“既然函数是一等公民, 我相信它不止这点能耐吧?“
“那是自然, 我们这里的函数还可以作为参数传递给另外一个函数呢!”
小王子突然想到父王给自己讲过,要在Java8中引入函数式编程。
可以把一个所谓的lambada 表达式传递给另外一个函数, 省去了创建类或匿名类的开销。
但是宫廷老师偷偷地告诉过自己:
“那只是半吊子的函数式编程,每个lambda表达式其实还得和一个函数接口相匹配, JDK在背后做了类型的推断”
“函数既然能作为参数,我猜肯定也能作为返回值吧?”
小王子觉得拜函数教的邱大教主在场, 这个天真活泼的小兰好像不敢给自己透露太多, 只好主动发问。
“你这个外乡人很聪明嘛, 估计有不少编程基础吧?”
小兰又展示了一段代码:
果然和自己的猜想一致!
作为皇族,小王子确实非常聪明,他很快就想到了另外一个问题:
“如果内部的eat函数访问了外部函数的变量会发生什么状况?”
按照我们Java 帝国的理论, 函数在被调用的时候是以栈帧的方式被压入栈中的。
函数的局部变量也在栈帧当中, 当这个函数返回,对应的栈帧就会被清除,局部变量自然也不可用了。
现在这个eat函数还能再使用createEatFunction()函数的desc这个变量吗?
或者在调用它的时候会使用外边的全局desc 变量?
从而输出 "dog 正在吃东西”?
函数作为返回值看起来很美, 但细节着实让人费解啊?
[*] 闭包
看到小王子像上次一样又“卡”住发呆了, 眼镜官员笑着对主教和小兰说:
这小子肯定又在深思了。
小兰说:
“这个外乡人确实不一般,思考很深入,让他的CPU再运转一会儿吧”
小王子没有找到答案,从思考中回来,看到大家都盯着自己看。
有点不好意思, 把疑惑给大家说了。
“外乡人,Java 把你毒害得不浅, 我看你资质不错,不如忘掉Java 那丑陋的模型, 加入到我们拜函数教来吧。 将来你继承我的位置也未可知啊!”
邱大教主看了小兰一眼,意味深长地说。
小兰接口说:
“还是先解释下你的疑惑吧, 你那段代码的输出应该是‘dog is eating’ , 而不是 ‘dog 正在吃东西’”
小王子说:
“这我猜到了, 我就是不理解一个函数(createEatFunction)都执行完了, 为什么它的变量(desc)还能被 后面执行的函数(eat)来使用。”
“要不说你的java毒中的很深啊, 你换个角度想想,局部变量在函数执行完以后还可以被访问。那它肯定不能存在于你说的那个什么java栈帧中。” 小兰说。
“那它放在那里?”
“在JavaScript 当中,有个作用域链(scope chain)的东西,它定义了一个函数激活执行的时候去哪儿找变量的值,比如eat函数的作用域链是这样的:”
此图只是示意图,并不严谨,例如没有表达出Activation object, Variable Object等概念
小王子看着这个图,马上就明白了,这个eat函数没有定义desc 这个变量。
所以就沿着链去查找, 在createEatFunction作用域去查找。
如果还找不到,就到global 作用域中查找......
这个例子中,在createEatFunction的作用域中有定义,于是就直接使用了。
“可是,createEatFunction 已经执行完了, 难道它的desc 变量不删除吗? ”
小王子不服气地说 。
“那肯定不能删除喽”
小兰说
“这里和你熟悉的java 有个重要的不同, 当你执行creatEatFunction的时候, eat函数才会被创建出来,此时eat函数就会把外部函数的作用域链记录下来(其中包含desc=' is eating'),以便执行时使用”
“哦,这个作用域是在函数创建时刻发生关联的,而不是运行时刻”
“没错, 这叫做静态作用域(static scope),或者叫词法作用域(lexical scope)。当eat函数被激活执行,就可以在createEatFuncction中找到desc的值,而不是在全局中找到desc的值。 ”
小兰接着说。
“我再给你看个例子, 你就理解这个静态作用域了”
小王子说:
“这段代码的输出应该是2 啊, 还有什么可说的,哦,不对不对,应该输出1, 静态作用域! 函数foo在创建的那一刻, 已经确定了它会和包含x=1的全局作用域关联 , 所以在运行的时候也只会从全局作用域查找,而不是从bar 函数的作用域中找x ”
“看来你已经Get到了, 这个静态作用域是实现闭包的一个必需条件, 你听说过闭包吧?”
小王子说:
“我听父王说过,但是不知道怎么回事....”
小王子说漏了嘴,赶紧打住。
小兰像没有听到一样,继续讲闭包:
“闭包在JavaScript当中就是一个函数和以静态方式存储的父作用域的一个集合体,通过这个集合体,一个函数就可以访问外部函数的变量了。 ”
“所以eat函数就可以访问外部函数的变量了!闭包这个名称有点古怪,不过背后的概念还是比较清晰的”
小王子赶紧说。
[*]尾声
“咳咳,小莱你够了。客人都被你吓到了。”
这时,在旁边默默看着的邱大教主说话了。
经过这一番交谈,小王子震惊于函数式的独特之处,尤其是和Java帝国的不同。
不过毕竟是皇族,阅历丰富,他还是悟出了一点门道。
“我大概明白了一点,由于 JavaScript 是动态类型,其实无论是函数还是对象,在这里都可以做为一个值来传递。函数式里面偏向对值直接进行处理,通过对这些值的传递和组合,就可以组装实现更高级的功能。”
“不错不错,我看你这位朋友的来头可不一般啊,新加入的信徒大多都经过漫长的适应期才能理解,他却立即悟出这些道理来。”
邱大教主对小王子赞赏有加,或许以他的智慧已经识破了小王子的身份。
“不不不,还是因为小兰妹妹讲的好啊。”
小王子脸红的说道。
“这还不是多亏了我们的原型才能自由灵活的实现各种编程范式么。”
眼镜大哥也参合了起来。
“哈哈哈,你又在自夸了。”
“来,说了这么多 eat,不说了,吃菜吃菜~”
**** Hidden Message *****
我操,Java还有这限制!一定要创建object? 看看 问下这个老刘是谁? 666 0 ·1 1 謝謝提供資料 啊啊啊感觉没太看懂。。。 1
页:
[1]