用户脚本问题:数组元素页面检测后alert显示undefined及无匹配刷新
解决你的用户脚本问题
咱们逐个拆解你遇到的两个问题,都是JavaScript里很常见的异步和作用域小坑~
问题1:弹出正确的找到元素(不再显示undefined)
你碰到的是异步函数与循环作用域的经典问题!setTimeout是异步执行的,当它触发弹窗时,外面的for循环早就跑完了——此时i的值已经等于数组长度(也就是2),item[2]自然就是undefined。
给你两种简单的解决思路:
方法1:用ES6的let声明循环变量
把循环里的var i改成let i,let会在每次循环迭代时创建独立的作用域,异步函数就能捕获到当前迭代的i值:
var item = [ 'apple', 'peach' ]; let found = false; // 标记是否找到元素 for (let i = 0; i < item.length; i++){ if(document.body.innerHTML.toString().indexOf(item[i]) > -1){ player.play(); found = true; setTimeout(function() { alert(item[i] + " was found"); }, 200); } }
方法2:用forEach遍历数组(更直观)
forEach的回调函数会为每个元素创建专属作用域,从根源上避免作用域混乱:
var item = [ 'apple', 'peach' ]; let found = false; item.forEach(function(curItem) { if(document.body.innerHTML.toString().indexOf(curItem) > -1){ player.play(); found = true; setTimeout(function() { alert(curItem + " was found"); }, 200); } });
问题2:未找到任何元素时自动刷新
我们可以加一个标记变量(比如上面的found),循环开始时设为false,只要找到任意一个元素就把它改成true。循环结束后,检查如果found还是false,就执行刷新逻辑:
把这段代码加在循环结束后:
if (!found) { setTimeout(function() { location.reload(true); }, 4000); }
完整的最终代码
整合后的代码用forEach版本会更清晰:
var item = [ 'apple', 'peach' ]; let found = false; item.forEach(function(curItem) { if(document.body.innerHTML.toString().indexOf(curItem) > -1){ player.play(); found = true; setTimeout(function() { alert(curItem + " was found"); }, 200); } }); // 未找到任何元素时4秒后刷新 if (!found) { setTimeout(function() { location.reload(true); }, 4000); }
这样既解决了弹窗显示undefined的问题,也实现了未找到元素自动刷新的需求~
内容的提问来源于stack exchange,提问作者Daniel Almeida
相关产品推荐
相关产品推荐

