web前端面试一道面试题

今天面试的时候一道面试题,大概是这样的,感觉自己很绕,希望大家帮我看下。谢谢。
问题是下面会输出3次1吗,如果不会,能修改使其实现吗?

function newFun(a){
        return function(a){
            console.log(a)
        }
    }
function fun(a) {
    console.log(a)
    newFun((a)=>{
        console.log(a)
    })
}
fun(1)
阅读 4.3k
8 个回答

当然不会了,人肉单步一下就知道了,跳过声明,从fun(1)进入,请跟着序号走

function newFun(a) {  // 2-1: 调用newFun,参数为刚刚的箭头函数
    return function(a) {  // 3: 返回一个匿名函数,这个匿名函数接受并打印参数a
        console.log(a);
    }
    // 4-0: 函数newFun结束
}

function fun(a) {  // 0-1: 调用fun,参数1
    console.log(a);  // 1: 打印a,即参数1
    newFun(a => {  // 2-0: 调用newFun,参数为一个箭头函数(注意这个函数是作为参数被声明的,此时这个函数还没有被调用)
        console.log(a);
    });
    // 4-1: 函数newFun的调用已经结束,并且它返回了一个匿名函数,但这个匿名函数没有被一个变量接收
    // 5-0: 函数fun的调用已经结束,该函数没有返回任何值
}

fun(1);  // 0-0: 调用fun,参数1
// 5-1: 函数fun的调用已经结束,脚本结束

可以看出从头到尾只打印了一次1,只有函数fun中的第一个console.log(a)会被执行,作为迷惑你的另外两个console.log(a)分别在两个作为参数和返回值的函数中,但没有被调用。要使得这两个console.log(a)被执行,只要调用其所属的函数即可

function newFun(a) {  // 3-1: 调用newFun,参数为刚刚的箭头函数
    return function(a) {  // 4: 返回一个匿名函数,这个匿名函数接受并打印参数a
        console.log(a);
    }
    // 5-0: 函数newFun结束
}

function fun(a) {  // 0-1: 调用fun,参数1
    console.log(a);  // 1: 打印a,即参数1
    let brandNewFun = a => console.log(a);
    brandNewFun(a);  // 2: 调用brandNewFun,参数为a,即1
    newFun(brandNewFun)(a);  // 3-0: 调用newFun,参数为一个箭头函数brandNewFun(注意这个函数是作为参数的,此时这个函数没有被调用)
    // 5-1: 函数newFun的调用已经结束,并且它返回了一个匿名函数,且我们立即调用了这个匿名函数,参数为a,即1,因此这里输出1
    // 6-0: 函数fun的调用已经结束,该函数没有返回任何值
}

fun(1);  // 0-0: 调用fun,参数1
// 6-1: 函数fun的调用已经结束,脚本结束

可以改成这个样子(有点变态啊):

 function newFun(a){
            return function(a){
                console.log("3->"+a)
            }
        }
    function fun(a) {
        console.log("1->"+a)
        newFun(((a)=>{
            console.log("2->"+a)
        })(a))(a)
    }
fun(1);

运行结果

1->1
2->1
3->1
新手上路,请多包涵

肯定不会输出3个1,首先箭头函数当参数并没有执行,其次箭头函数里执行后的a值也需要返回出来,不然是undefined,可以把这样来看a是从哪儿来的:

function newFun(a){
        console.log(`C: ${a}`);
        return function(j){
            console.log(`D: ${j}`);
        }
    }
    function fun(a) {
        console.log(`A: ${a}`);
        newFun(((i)=>{
            console.log(`B: ${i}`);
            return i;
        })(a))(a)
    }
    fun(1)

大改步骤为:

    function newFun(a){
        return (a => {console.log(a + ">>>3")})(a);
    }

    function fun(a) {
        console.log(a + ">>>1");    //1
        newFun( (a => {console.log(a + ">>>2");return a})(a));
    }
    fun(1);

可能会更绕,你可以好好看看一楼的解释

 //类似Thunk函数
function newFun(...args){
        return function(fn){
            console.log(...args)
            return    fn.call(this,...args)
        }
    }
function fun(a) {
    console.log(a)
    newFun(a)((a)=>{
        console.log(a)
    })
}
fun(1)
function fun(a) {
    console.log(a)
    return function(a) {
        console.log(a)
    }
}
fun(1)

好像最后也就执行了一个console.log吧。

新手上路,请多包涵

function newFun(a){

    console.log(a)
    return function(a){
        console.log(a)
    }
}

function fun(a) {

console.log(a)
newFun(a)(a)

}
fun(1)

原代码不会输出3次1。

以下是对执行过程的分析,手动diff了一下,方便看出和原代码相比,修改了哪些地方。

function newFun(a) {
+   a() // 3: 调用函数a(a就是第2步调用newFun时传入的那个箭头函数)
    return function(a) { // 5: 返回一个匿名函数
        console.log(a) // 7: 第三次输出1(这边的a和newFun的a不是同一个,这个a的值是由第6步调用时的传入的值决定的)
    }
}
function fun(a) {
    console.log(a) // 1: 第一次输出1

-   newFun((a)=>{
-       console.log(a)
-   })
+   newFun(()=>{ // 2: 调用newFun,newFun的参数是一个箭头函数
+       console.log(a) // 4: 第二次输出1
+   })(a) // 6: 调用newFun时返回了一个匿名函数(即第5步返回的那个匿名函数),此处调用该匿名函数,参数是a(a的值为1)
}

fun(1) // 0: 调用fun

以下代码可直接拷贝,方便想打断点了解执行过程的人。

function newFun(a) {
    a() // 3: 调用函数a(a就是第2步调用newFun时传入的那个箭头函数)
    return function(a) { // 5: 返回一个匿名函数
        console.log(a) // 7: 第三次输出1(这边的a和newFun的a不是同一个,这个a的值是由第6步调用时的传入的值决定的)
    }
}
function fun(a) {
    console.log(a) // 1: 第一次输出1

    newFun(()=>{ // 2: 调用newFun,newFun的参数是一个箭头函数
        console.log(a) // 4: 第二次输出1
    })(a) // 6: 调用newFun时返回了一个匿名函数(即第5步返回的那个匿名函数),此处调用该匿名函数,参数是a(a的值为1)
}

fun(1) // 0: 调用fun
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题