一个学习案例中遇到的问题
index.html
<div class="d-flex gap-3"> <div class="box"></div> <div class="box"></div> <div class="box"></div></div>
index.css
.box { width: 100px; height: 50px; border: 1px solid;}
index.js
var boxs = document.getElementsByClassName('box');for (var i = 0; i < boxs.length; i++) { boxs[i].onclick = function () { // i = 1,2,3 console.log(i); // i = 3 }}
上述代码中, 我在循环里为每个 .box
添加点击事件, 但是在事件里的i始终是循环体执行完毕后的结果 3, 为什么会出现这种情况?
因为之前写代码在 onclick 事件里基本都是用 this, 或者用 let 来代替 var 来定义变量, 所以绕过了这个坑
但现在遇到了这样的 bug, 还是想问下导致这个问题的原因是什么?
关于 var 的特性, 我能想到的是 全局污染和变量提升, 简单地说
但是上述两个特性都不能合理的解释 -> 为什么在for循环中定义的onclick, 循环变量i在onclick事件中永远是for最终执行后的i?
补充下,这题知识点是js 的作用域, 点击按钮的时候打印i, js引擎会去找click函数外部的作用域,变量i 的值。然而触发click事件时,<script> 引入的代码早就执行完了【此时i 为3】。你打个断点去chorme debugger, 一步步执行下就可以理解了。js 知识内容建议去看《JavaScript忍者秘籍》。
这个循环转化这样就好理解了
var i = 0;{ boxs[i].onclick = function () { console.log(i); // i = 3 }}++i;{ boxs[i].onclick = function () { console.log(i); // i = 3 }}++i;{ boxs[i].onclick = function () { console.log(i); // i = 3 }}
如果我们使用的是let
,可以这样理解
{ let t = 0; { let i = t; boxs[i].onclick = function () { console.log(i); // i = 3 } } ++t; { let i = t; boxs[i].onclick = function () { console.log(i); // i = 3 } } ++t; { let i = t; boxs[i].onclick = function () { console.log(i); // i = 3 } }}
补充一个比较好理解的
var i = 0;console.log(i); // 0var i = 3;
上述代码中输出的 i = 0
, 因为 console.log()
是同步方法, 当它执行完毕后才会执行下面的 i = 3
var i = 0;boxs[i].onclick = function() { console.log(i); // 3}var i = 3;
而在 onclick
中, 因为是一个异步方法, 所以执行到时不会发生阻塞, 而是同时执行了 i = 3
, 导致最终 click
触发时 i
的值已经是 3 了
你换个思路,在你的代码中有几个i呢,是不是只有一个,所有当for循环结束i的值也只能是一个,因为i一个变量不可能同时又是1又是2又是3
这个问题的原因是 JavaScript 的变量提升(Hoisting)特性。
在 JavaScript 中,变量的声明会被提升到其所在作用域的顶部,但赋值操作不会。在你的代码中,var i
这一行代码被提升到了循环的顶部,但赋值 i = 0
、i = 1
和 i = 2
这些操作并没有被提升。
所以,当你在循环中点击 .box
元素时,实际上 i
的值已经被设为了 3
。这是因为循环结束后,i
的值已经变成了 3
,并且这个值被赋给了每个 .box
元素的 onclick
事件处理器。
如果你希望在事件处理器中 i
的值是 0
、1
或 2
,你需要将 var i
改为 let i
。使用 let
关键字声明的变量有块级作用域,并且不会发生变量提升。这样,每个 .box
元素的 onclick
事件处理器都会在其自己的作用域中获取到正确的 i
值。
以下是你的代码,其中将 var i
改为了 let i
:
<div class="d-flex gap-3"> <div class="box"></div> <div class="box"></div> <div class="box"></div></div>
.box { width: 100px; height: 50px; border: 1px solid;}
var boxs = document.getElementsByClassName('box');for (let i = 0; i < boxs.length; i++) { boxs[i].onclick = function () { // i = 0,1,2 console.log(i); // i = 0,1,2 }}
上面是代码,想执行'person1.func3()'。 结果如下图
关于正则的一个小问题 /#\/((\w)+)/.exec("/a-web/#/abc?") 返回值是 ['#/abc', 'abc', 'c', index: 7, input: '/a-web/#/abc?', groups: undefined] 数组第二项是匹配项(\w+) 返回 'abc' 数组的第三项 返回值 'c'怎么理解啊 没啥尝试
我已经开始做一个游戏,有点类似于“花比尔盖茨的钱”,但我说过要稍微改变一下。我做了第一项,我试着用JS编辑它,所以每次你按“买”,它会从你身上移除1美元,或者,当你按“卖”给你1美元。问题是,每次我点击,它只算一次。另外,如果我按“买进”,然后按“卖出”,它会立即给我11美元,而不是10美元。文件名:index.html 文件名:script.js
问题1: 类似微信这样的安装在用户个人设备上的软件,调整了后端接口服务后,需要用户更新设备上的软件,如果用户没更新,还是能正常使用,一般这种是采取什么方案处理的?是调整后的接口服务,仍然支持旧版本的软件使用吗? 问题2: 假设我有个web系统,全国各地都有门店在使用,有些门店需要使用频繁更新后的web系统(),有些门店只需要偶尔更新web系统。这些门店使用的web系统都是同一个域名。有什么方案,在
本文向大家介绍JavaScript中关于base64的一些事,包括了JavaScript中关于base64的一些事的使用技巧和注意事项,需要的朋友参考一下 base64 其实是一种编码转换方式, 将 ASCII 字符转换成普通文本, 是网络上最常见的用于传输8Bit字节代码的编码方式之一。 base64 由字母 a-z 、 A-Z 、 0-9 以及 + 和 / , 再加上作为垫字的 = , 一共6
问题内容: 我在一个div内放了一个嵌入式Flash电影,在主div上放了一个javascript onclick事件处理程序,但是没有捕捉到点击,这是怎么回事? 码: 问题答案: 最好将所有swf都视为z阶无穷大。Flash是最重要的,只有很少的事情可以阻止它。另一方面,如果您可以访问SWF本身的代码,或者可以使用另一个SWF加载当前的SWF,则可以使用几个不同的Flash命令来处理页面的Jav