程序员面试系列
Java面试系列-webapp文件夹和WebContent文件夹的差异?
程序员面试系列:Spring MVC能呼应HTTP恳求的原因?
Java程序员面试系列-什么是Java Marker Interface(符号接口)
运用JDK自带的东西jstack找出形成运转程序死锁的原因
编程面试题:编写一个会形成数据库死锁的运用
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(符号接口)
运用JDK自带的东西jstack找出形成运转程序死锁的原因
编程面试题:编写一个会形成数据库死锁的运用
JavaScript面试系列:JavaScript规划形式之桥接形式和懒加载