freeCodeCamp Twitchtv API项目:AJAX调用报错及循环内函数问题求助
解决循环内放置函数的JSHint警告(Twitch API项目)
嘿,我完全懂你在做freeCodeCamp中级前端项目时碰到的这个JSHint警告问题!首先得搞明白为啥会出这个提示——循环里定义函数(比如你大概率在循环里写了AJAX请求的回调)会引发作用域绑定的坑,等异步操作执行的时候,循环变量i早已经变成数组的最后一个索引了,而且JSHint也把这种写法当成潜在bug的高发区。
先看你给出的代码片段,虽然没写完,但推测你本来是想在循环里逐个请求Twitch API对吧?咱们一步步来修复:
问题根源
假设你原本的循环逻辑是这样的(补全了合理的API地址和AJAX请求):
$("document").ready(function() { var streamers = [ "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas" ]; var htm = ""; for (i = 0; i < streamers.length; i++) { var url = "https://wind-bow.gomix.me/twitch-api/streams/" + streamers[i]; // 这里的回调函数就是JSHint警告的核心原因 $.get(url, function(data) { // 处理返回数据时会发现streamers[i]是undefined htm += `<div>${streamers[i]}</div>`; }); } });
这里的问题是,所有回调函数共享同一个i变量,当AJAX请求完成时,循环早就跑完了,i的值已经是streamers.length(也就是8),导致streamers[i]取不到正确的主播名,同时触发JSHint的警告。
解决方案
1. 用ES6的let声明循环变量
这是最简洁的现代解法,let会在每次循环迭代时创建一个新的变量绑定,每个回调函数都会捕获当前迭代的i值:
$("document").ready(function() { const streamers = [ "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas" ]; let htm = ""; // 用let声明i,每次迭代都有独立绑定 for (let i = 0; i < streamers.length; i++) { const url = `https://wind-bow.gomix.me/twitch-api/streams/${streamers[i]}`; $.get(url, function(data) { htm += `<div>${streamers[i]}: ${data.stream ? '在线' : '离线'}</div>`; // 记得更新DOM $('#stream-container').html(htm); }); } });
2. 用立即执行函数(IIFE)创建闭包
如果需要兼容旧浏览器,不能用ES6的let,可以用IIFE把每次迭代的i封装起来,形成独立作用域:
$("document").ready(function() { var streamers = [ "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas" ]; var htm = ""; for (var i = 0; i < streamers.length; i++) { // 用IIFE捕获当前迭代的i值 (function(currentIndex) { var url = "https://wind-bow.gomix.me/twitch-api/streams/" + streamers[currentIndex]; $.get(url, function(data) { htm += `<div>${streamers[currentIndex]}: ${data.stream ? '在线' : '离线'}</div>`; $('#stream-container').html(htm); }); })(i); } });
3. 改用forEach遍历数组
forEach的回调函数会自动为每个元素创建独立作用域,完全避开循环变量绑定问题,代码也更清爽:
$("document").ready(function() { const streamers = [ "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas" ]; let htm = ""; streamers.forEach(function(streamer) { const url = `https://wind-bow.gomix.me/twitch-api/streams/${streamer}`; $.get(url, function(data) { htm += `<div>${streamer}: ${data.stream ? '在线' : '离线'}</div>`; $('#stream-container').html(htm); }); }); });
这三种方案都能搞定JSHint的警告,同时解决异步操作里的变量绑定bug。个人更推荐forEach或者let的写法,代码可读性更高。
内容的提问来源于stack exchange,提问作者Ayudh Khajne
相关产品推荐
相关产品推荐

