使用JavaScript ES6的新特性计算Fibonacci(非波拉契数列)
程序员面试系列
Java面试系列-webapp文件夹和WebContent文件夹的区别?
程序员面试系列:Spring MVC能响应HTTP请求的原因?
Java程序员面试系列-什么是Java Marker Interface(标记接口)
JavaScript面试系列:JavaScript设计模式之桥接模式和懒加载
面试题:用JavaScript开发一个函数,打印非波拉契数列。
我们只要记住非波拉契数列的计算公式,就不难写出来了:
F(0)=1,F(1)=1, F(n)=F(n-1)+F(n-2)
我写的JavaScript代码如下:
var fib = function (a, b) {
var _current = a + b;
return {
current: _current,
next: function () {
return fib(b, _current);
}
}
}
把当前这一轮的计算结果存储到第二行的变量_current里,并通过属性current返回给调用者。返回的json对象除了current属性外,还有另一个属性next,指向一个闭包函数调用。一旦next指向的函数再次被调用,则会再次触发数列的计算。
var generator = fib(1,1);
// 前一行调用fib(1,1)计算1+1的结果为2,将2存储到_current里通过current属性返回,所以打印2
// 同时返回next函数,函数体为return fib(b, _current); 此时b为1,_current为2
console.log(generator.current);
// 一旦执行next函数,则执行其指向的return fib(b, _current); 1 + 2 = 3
var result = generator.next();
console.log(result.current); // 打印3
如果要打印10个非波拉契数列的值,意味着我要重复调用9次fib函数,太麻烦。于是我写了个函数把fib调用包裹起来。
这个包裹函数有两个输入参数,n为希望生成非波拉契数列元素的个数,第二个参数sequence接受一个函数。
var take = function(n, sequence) {
var result = [];
var temp = sequence;
for (var i = 0; i < n; i++) {
result.push(temp.current);
temp = temp.next();
}
return result;
}
现在我只需要一行语句,就能打印10个非波拉契数列的元素出来。
console.log(take(10, fib(1,1)));
采用ES6的GeneratorFunction生成非波拉契数列
ES6提供了原生GeneratorFunction的支持,语法非常有特色,关键字function后面紧跟一个星号。GeneratorFunction的详细介绍参考官网:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
先看如何用GeneratorFunction这个黑科技重新实现非波拉契树立的生成。代码如下:
var fib_generator = function *(){
var current = 0, next = 1;
while(true) {
[next, current] = [next+current, next];
yield current;
}
}
var fib = fib_generator();
for(var i = 0; i < 10; i++){
console.log(fib.next().value);
}
第5行从语义上非常清晰地体现出了非波拉契数列的计算公式:
F(n)=F(n-1)+F(n-2)
然而它是包含在一个while(true)的无限循环内的,所以这段代码是如何工作的呢?
最好的学习办法就是单步调试。
代码第40行到第47行,我们使用了ES6 function*关键字得到了一个"function generator"。在这个generator内部,我们定义了一个无限循环,用于计算非波拉契数列。
第49行,我们用()调用了这个generator,将结果存储在变量fib里。直到此时,function generator的实现体,即代码41~45行还没有得到执行。
实际上,49行的变量lib只是维护了一个指向fib_generator的ITERATOR指针。
这个ITERATOR自带了一个名为next的方法,是ES6的原生实现,大家看上图调试器里的fib.next显示的是native code。Functiongenerator的神奇之处在于,当next方法被调用一次,则generator内部的函数体也只会执行一次。
单步执行,执行一次next方法:
注意调用栈,此时我们已经进入fib_generator函数体内部了:
一旦在FunctionGenerator实现体内部执行到yield关键字,则当前计算结果作为返回值返回给consumer。也就是说,一旦执行遇到yield,则自动从无限循环中退出。
下列简单的循环会打印10个非波拉契数列的元素:
for(var i = 0; i < 10; i++){
var currentResult = fib.next();
console.log(currentResult.value);
}
从上面的代码能看出,yield关键字返回一个json对象给消费者,该对象有个名为name的属性,包含的是具体计算的数值。Json对象的另一个属性名为done,类型为boolean,意思是这个FunctionGenerator的函数体执行是否已经结束。在我的这个例子里,每次next调用的yield返回的Json对象的done属性都为false,因为我的FunctionGenerator内部是一个无限循环。
采用ES6的FunctionGenerator打印出的结果和常规写法一致。
相信您面试的时候,如果能用ES6的FunctionGenerator完成这道题目,一定能让面试官对您刮目相看。
我写的程序员面试系列
Java面试系列-webapp文件夹和WebContent文件夹的区别?
程序员面试系列:Spring MVC能响应HTTP请求的原因?
Java程序员面试系列-什么是Java Marker Interface(标记接口)
JavaScript面试系列:JavaScript设计模式之桥接模式和懒加载
要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:


使用JavaScript ES6的新特性计算Fibonacci(非波拉契数列)的更多相关文章
- 如何在ABAP里用函数式编程思想打印出非波拉契Fibonacci(数列)
在JavaScript里可以用ES6提供的FunctionGenerator这种黑科技来打印非波拉契数列,具体细节参考我这篇文章. 在ABAP里也有很多种方式实现这个需求. 下面这个report分别用 ...
- 关于斐波拉契数列(Fibonacci)
斐波那契数列指的是这样一个数列 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233,377,610,987,1597,2584,4181,6765,10 ...
- python的生成器(斐波拉契数列(Fibonacci))
代码: 函数版本: #斐波拉契数列(Fibonacci) def fib(max): n=0 a,b=0,1 while n < max: a,b = b,a+b n = n+1 return ...
- 斐波拉契数列(用JavaScript和Python实现)
1.用JavaScript 判断斐波拉契数列第n个数是多少 //需求:封装一个函数,求斐波那契数列的第n项 //斐波拉契数列 var n=parseInt(prompt("输入你想知道的斐波 ...
- 递归算法之Fibonacci 斐波那契数列第n个数的求解
Fibonacci 斐波那契数列第n个数的求解,也可以用递归和非递归的形式实现,具体如下,dart语言实现. int fibonacci(int n) { if (n <= 0) throw S ...
- lintcode:Fibonacci 斐波纳契数列
题目: 斐波纳契数列 查找斐波纳契数列中第 N 个数. 所谓的斐波纳契数列是指: 前2个数是 0 和 1 . 第 i 个数是第 i-1 个数和第i-2 个数的和. 斐波纳契数列的前10个数字是: 0, ...
- 算法导论-求(Fibonacci)斐波那契数列算法对比
目录 1.斐波那契数列(Fibonacci)介绍 2.朴素递归算法(Naive recursive algorithm) 3.朴素递归平方算法(Naive recursive squaring) 4 ...
- 斐波拉契数列(Fibonacci)--用生成器生成数列
斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数列&qu ...
- Fibonacci(斐波那契数列)的最佳实践方式(JavaScript)
1)低级版本 var fibonacci = function(n) { if (n == 0 || n == 1) { return n; } else { return fibonacci(n - ...
随机推荐
- Interval query
题意: 给出数轴上的N个区间,M个询问"QUERY(a, b)", 意为[a, b]之间不相交的集合的最大数量是多少. 解法: 考虑 $O(n)$ 的贪心做法,预处理出对于每一个位 ...
- git远程提交到github或者gitee
一.git安装 git官网下载 https://git-scm.com/downloads ,既有Windows的.Linux的以及Macos的. windowds下载安装git的可执行文件,就会有两 ...
- Httpclient入门代码
/** * Project Name:httpClient * File Name:Test.java * Package Name:httpClient * Date:2017年11月9日上午8:3 ...
- 2.12 Hivet中order by,sort by、distribute by和cluster by
https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SortBy 一.order by 对全局数据的排序,仅仅只有一个red ...
- 解决“System.Data.OracleClient需要Oracle客户端软件8.1.7或更高版本”
问题描述:远程访问该数据库(客户端同样是Oracle11g)提示“System.Data.OracleClient需要Oracle客户端软件8.1.7或更高版本”. 解决的办法: 1.一定要关闭Win ...
- 真正可用的Asdoc生成工具及技巧和注意事项
经过一个上午的折腾,终于总结出一套完全能够正确运行得到asdoc api的工具.使用方便,里面写了许多注意事项,帮你顺利完成 api 的生成. :: 注意: :: 1.所以 ...
- 阿里云的opensearch
官方文档:https://help.aliyun.com/document_detail/29104.html?spm=a2c4g.11186623.6.544.5215187be2TnnD
- hdu 4694 Important Sisters【支配树】
求出支配树输出到father的和即可 支配树见:https://blog.csdn.net/a710128/article/details/49913553 #include<iostream& ...
- IT兄弟连 JavaWeb教程 MVC设计模式
MVC是Model-View-Controller的简称,即模型-视图-控制器.MVC是一种设计模式,它强制性地把应用程序的数据展示.数据处理和流程控制分开.MVC把应用程序分成3个核心模块:模型.视 ...
- 关于MySQL集群架构优劣势与适用场景的分析与思考
http://blog.itpub.net/25723371/viewspace-1977389/