Web 浏览器中的开发者工具都会提供一个控制台(或者也叫命令行)。在调试 JS 时,在控制台中打印变量或者测试代码片段都很方便。某日,在调试 JS 代码中,在控制台打印一个变量却出现ReferenceError: varialbe is not defined错误,令我感到迷惑不解。场景大致如下:
var getSth = function (key) { $.ajax({ url: '/echo/json', type: 'GET', data: {key: key}, dataType: 'json' }).done(function (data) { console.log(key) })}AJAX请求成功执行匿名回调函数时,console.log语句会正常打印key值。但将console.log(key)改为 console.log(data),通过开发工具在此处设置一个断点,代码执行在断点处时在控制台中打印key,则会报错ReferenceError: key is not defined。
一开始想当然的认为key变量是通过查找作用域链获得,反复调试后发现,如果在匿名回调函数的代码中引用key变量的话,则会在当前作用域创建一个闭包,而 JavaScript 是基于词法作用域,闭包的创建是在词法分析阶段,所以在代码执行时通过控制台动态的引用key值会得到一个ReferenceError。