Web前端面试题:写一个mul函数

问题:写一个mul函数调用时将生成以下输出:

console.log(mul(2)(3)(4)); // output : 24

console.log(mul(4)(3)(4)); // output : 48

 

回答:时允

这个应该是题主想要的答案,支持任意次数调用。主要是考察了对递归的理解,和 valueOf 的使用。
function mul(x) {
	const result = (y) => mul(x * y); 
	result.valueOf = () => x;
	return result;
}

console.log(mul(3))
-> 3
console.log(mul(3)(2))
-> 6
console.log(mul(3)(2)(4))
-> 24
console.log(mul(3)(2)(4)(5))
-> 120

涉及到的知识点大概有:

1.const

2.function类型

3.lambda表达式

4.valueOf

5.递归

1.const是es6的新语法,用法基本和var一样(这里换成var或者let也可以运行)。在本答案中有一个精妙的点是result本身由于是const,不能被重复赋值,但是result作为一个object(Function Object),他的每一个key是不受保护的,所以result的valueOf是可以被重写的。

const

2.当使用typeof查看一个function的类型的时候,结果是"function" 然而所有的function其实都是Object(Function Object), 这也是为什么它会调用到Object.prototype.valueOf()的原因

Every Object is a function and every function is Object - Which is Correct?

3.lambda表达式(Lambda Expression or Arrow Function),是es6提供的新语法,

() => x 可以看做是 function(){ return x; }

(y) => mul(x * y) 可以看做是 function(y){ return mul(x * y) }

Arrow functions

4.valueOf在这里是Object的一个方法,这个方法没有参数并返回了一个基本类型。在所有对object的取值过程都会被调用。前面说了function其实也是一个Object,所以在对这个function进行取值(比如做乘法)的时候,就会调用这个valueOf,如果是正常使用,他返回的其实是mul()这个function本身。

Object.prototype.valueOf()

5.递归比较难说明,我试着举例说明,

当运行mul(3)的时候,3作为参数被传入,这个函数的返回值其实是

function(y){ return mul(3 * y);}

然而!!这个函数被取值的时候,调用了的是valueOf方法,而这个函数的valueOf方法是

function(){ return 3;}, 所以你尝试输出他的时候,得到的值是3.

当运行mul(3)(2)的时候,由于前面说过函数的返回值是一个匿名函数

function(y){return mul(3 * y)}

在这里就是(mul(3))(2), 也就是function(2){ return mul(3 * 2);},

所以当在最后被取值的时候,运行的其实是mul(3*2)的valueOf方法,也就是

function() { return 3 * 2; }

所以得到的结果是6.

另外有看到别的评论有提到在nodejs环境,和firefox浏览器下,console.log()并不调用valueOf,我做了个实验。如图:

Web前端面试题:写一个mul函数

证明在nodejs环境下,console.log()的确不调用valueOf,所以题主的答案应该视当时情况而定。

地址:https://www.zhihu.com/question/54822257/answer/141698567

 

上一篇:对于上次学生成绩管理系统IO流的改进


下一篇:js-js系列-数据类型-转换