非jQuery环境下在循环中使用this无效,原因是什么?
为什么原生JS循环中用
this[i]无法正常工作? 你遇到的问题核心是**this关键字在不同执行场景下的指向差异**,咱们一步步拆解清楚:
1. 先搞懂无效代码里的this指向哪里
当你直接调用doSomething()时,在非严格模式下,函数内部的this会指向全局对象(浏览器环境里就是window);如果开启严格模式,this会是undefined。
所以你写的this[i]其实是在尝试访问window[i],这和你通过document.querySelectorAll('a')获取到的链接数组完全没关系,自然没法修改a标签的href属性。
2. 对比jQuery的each为什么能用this
jQuery的.each()方法做了特殊的上下文绑定处理:它会把回调函数里的this自动绑定到当前遍历的DOM元素上,所以你在jQuery的回调里用this能精准拿到当前的a标签——这是jQuery帮你做了额外的工作,原生JS默认不会这么处理。
3. 原生JS的正确写法
写法一:沿用for循环,直接访问数组元素
这是你第一个有效代码的思路,直接用links[i]访问当前元素,直观且高效:
function doSomething() { var links = document.querySelectorAll('a'); for (var i = 0; i < links.length; i++) { links[i].setAttribute('href', links[i].getAttribute('href').replace('foo', 'bar')); } } doSomething();
写法二:用forEach遍历(更简洁的原生方式)
如果想追求类似jQuery的简洁感,原生的forEach可以直接拿到当前元素,不需要依赖this:
function doSomething() { var links = document.querySelectorAll('a'); links.forEach(function(link) { link.href = link.href.replace('foo', 'bar'); }); } doSomething();
这里的link参数就是当前遍历到的a标签,直接使用它比纠结this的指向更清晰。
写法三:非要用this?(不推荐,没必要)
如果只是好奇能不能用this实现,也可以通过call手动绑定上下文,但这种写法完全是绕弯路,仅作演示:
function doSomething() { var links = document.querySelectorAll('a'); for (var i = 0; i < links.length; i++) { (function() { this.setAttribute('href', this.getAttribute('href').replace('foo', 'bar')); }).call(links[i]); } } doSomething();
总结一下:原生JS里普通函数的this不会自动绑定到你遍历的数组元素上,只有像jQuery这类库的方法会帮你做这个绑定。所以直接用数组索引访问或者forEach的参数,才是原生JS里处理这类场景的正确姿势。
内容的提问来源于stack exchange,提问作者john c. j.
相关产品推荐
相关产品推荐

