Web前端面试题:写一个mul函数
问题:写一个mul函数调用时将生成以下输出:
console.log(mul(2)(3)(4)); // output : 24
console.log(mul(4)(3)(4)); // output : 48
回答:时允
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是可以被重写的。
const2.当使用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 functions4.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,我做了个实验。如图:
证明在nodejs环境下,console.log()的确不调用valueOf,所以题主的答案应该视当时情况而定。
地址:https://www.zhihu.com/question/54822257/answer/141698567