Javascript 当使用从父级传递的参数在函数内部调用时,为什么setTimeout函数日志记录未定义?

Javascript 当使用从父级传递的参数在函数内部调用时,为什么setTimeout函数日志记录未定义?,javascript,asynchronous,settimeout,event-loop,asynccallback,Javascript,Asynchronous,Settimeout,Event Loop,Asynccallback,我一直在使用javascript中的异步函数setTimeout。 当参数在一个setTimeout函数中传递而不是在另一个setTimeout函数中传递时,以下代码给出不同的结果。有人能解释一下吗 代码1: console.log("Before"); getUserId(2); console.log("After"); function getUserId(id){ setTimeout(() =>{ console.log(id); }, 2000); } 产出

我一直在使用javascript中的异步函数setTimeout。 当参数在一个setTimeout函数中传递而不是在另一个setTimeout函数中传递时,以下代码给出不同的结果。有人能解释一下吗

代码1:

console.log("Before");
getUserId(2);
console.log("After");

function getUserId(id){
  setTimeout(() =>{
    console.log(id);
  }, 2000);
}
产出1:

Before
After
2
以及

代码2:

console.log("Before");
getUserId(2);
console.log("After");

function getUserId(id){
  setTimeout((id) =>{
    console.log(id);
  }, 2000);
}
产出2:

Before
After
undefined

因为在示例1中,id设置在getUserId(id)的范围内
在示例2中,该id在该范围内再次设置,但随后通过匿名函数创建了第二个范围更窄的id。无需传递setTimeout()id参数,因为它已经存在于getUserId范围中

如果要将参数传递给
回调
,可以将它们放在
延迟
参数之后。如果您没有传递任何参数,那么您的回调将在没有任何参数的情况下被调用

setTimeout(function[, delay, param1, param2, ...]);
console.log(“之前”);
getUserId(2);
控制台日志(“之后”);
函数getUserId(id){
设置超时((id)=>{
console.log(id);
},100,id);

}
在第二个示例中,您正在重新定义传递给
setTimeout()
的回调中变量
id
的作用域。换句话说,这与:

function getUserId(id){
  setTimeout((some_other_id) => {
    console.log(some_other_id);
    // some_other_id is undefined
  }, 2000);
}

理解
id
的范围将解释/解决您的问题。

setTimeout回调中的参数id将是未定义的,除非您像示例一样为其指定默认值

function parentMethod(parentId) {
  setTimeout((id = parentId) => {
    console.log(id);
  }, 2000);
}
检查这条线
setTimeout((id=parentId)=>{


这里我给它分配了一个默认值,因此它将记录我分配给父方法的任何内容。

在setTimeout和getUserId函数的回调方法中,id的命名可能重复,这可能是第二个示例中让您感到困惑的地方,它们是两个不同范围的变量,您没有发送值在第一个示例中,id由闭包捕获。