两个输出相同的Javascript fakeAjax函数的具体区别是什么?
两个fakeAjax函数的核心区别
两种写法的执行逻辑完全不同,你看到输出相同只是测试场景下的巧合,本质差异如下:
第一种写法(正确的异步实现)
function fakeAjax(url,cb) { setTimeout(function fakeLoadingDelay(){ cb([ "A Song of Ice and Fire", "The Great Gatsby", "Crime & Punishment", "Great Expectations", "You Don't Know JS" ]); },500); }
- 传给
setTimeout的第一个参数是未执行的函数引用,JS会等500ms延迟结束后,才调用这个匿名函数,再执行传入的cb回调,完全符合异步模拟请求的设计预期。 - 执行流程:调用
fakeAjax→ 把延迟任务推入异步事件队列 → 立即结束fakeAjax的同步执行 → 500ms延迟到了之后才触发cb执行。
第二种写法(错误的异步实现)
function fakeAjax(url,cb) { setTimeout(cb([ "A Song of Ice and Fire", "The Great Gatsby", "Crime & Punishment", "Great Expectations", "You Don't Know JS" ]) ,500); }
- 传给
setTimeout的第一个参数是cb(数组)的执行返回值,也就是说cb会在调用fakeAjax的瞬间就同步立即执行,根本不会等待500ms。 - 只有当你的
cb函数执行后返回的是另一个函数时,setTimeout才会在500ms后调用这个返回的函数;如果cb没有返回值(默认返回undefined),setTimeout拿到无效参数,500ms后不会执行任何逻辑。 - 你看到输出相同的原因是测试时
cb同步执行和延迟执行的输出内容本身没有区别,没有感知到时机差异,你可以在cb内打印当前时间戳console.log(Date.now())再分别调用两次,就能看到明显的时间差。
额外说明
第二种写法是JS新手常见的错误,核心是混淆了「函数引用」和「函数调用的返回值」两个概念。如果你的cb依赖fakeAjax调用后才初始化的变量,第二种写法会直接报错,而第一种写法则能正常执行。
内容的提问来源于stack exchange,提问作者Nader Tarek
相关产品推荐
相关产品推荐

