今天学习AJAX的过程中,有两段示例代码,其中一段如下(另一段类似):
-
<div id="navigation">
-
<a id="beginners" title="beginners" href="#">Beginners</a>
-
<a id="intermediate" title="intermediate" href="#">Intermediate</a>
-
<a id="advanced" title="advanced" href="#">Advanced</a>
-
</div>
两段代码均做类似处理:
-
var buttons = document.getElementById("navigation").getElementsByTagName("a");
-
for (const i in buttons) {
-
var currentBtn = buttons[i];
-
currentBtn.onclick = showTab;
-
currentBtn.onmouseover = buttonOver;
-
currentBtn.onmouseout = buttonOut;
-
}
因为刚刚学习了jQuery所以我想用jQuery对其进行处理,所以我改为了如下代码:
-
var buttons = $("#navigation a");
-
for (const i in buttons) {
-
var currentBtn = buttons[i];
-
// = showHint;
-
// = hideHint;
-
// = showTab;
-
// = buttonOver;
-
// = buttonOut;
-
$(currentBtn).mouseover(showHint);
-
$(currentBtn).mouseout(hideHint);
-
$(currentBtn).click(showTab);
-
$(currentBtn).mouseover(buttonOver);
-
$(currentBtn).mouseout(buttonOut);
-
}
当两段代码都用jQuery替换时,运行界面会出现如下错误:
无奈,只能照抄书上,全部按JS写法,运行正常,于是我想着到底是怎么回事呢?
众所周知,()会获取DOM中第一个符合id的标签,而getElementsByTagName()则会返回符合标签名的所有标签,返回值是一个数组,对其所有处理必须使用下标;而jQuery的返回值则是一个jQuery元素,不能使用JS的方法,为了更直观的展现,我将两段代码一个用JS获取,一个用jQuery获取,并打印出来给大家看:
其中init是我的页面初始化函数,上面的是采用jQuery获取元素的返回值,下面的是JS获取的返回值,二者代码如下:
-
var tabs = $("#tabs a");
-
-
var buttons = document.getElementById("navigation").getElementsByTagName("a");
如果只是想把jQuery的获取对象使用JS的方法,只需要对其取下标[0]即可或者使用.get[0],比如$(currentTab)[0].onmouseover = showHint;等价于$(currentTab).mouseover(showHint);
而DOM对象转换为jQuery对象只需要加$即可:$(DOM)
但是对于我的代码而言,如果第一段出错,即toJSON错误,那么第一段功能正常,第二段无论使用jQuery还是JS都会失效,如果第二段是用jQuery出现toJSON错误,那么第一段第二段都正常(出现错误的那一段代码可以正常运行),这个原因我还没有查明,如果有大佬知道可以和我联系,谢谢!
—————————————————————手动分割线——————————————————————————————
后续来了,找了个学长问了下,确实是循环那里的问题,当时我debug的时候有想到,但是第一次修改后出现了其他bug,所以没有在意,以为循环没有问题,但现在重新debug后证实了确实是循环的问题:
Javascript 大忌之不要用for in语句对数组进行遍历
for in语句对一个数组进行遍历,如果原生Array类被其他脚本库扩展过,比如我遇到的toJOSN属性,那么会多循环一次,这将会是代码的逻辑发生错误,所以对于数组来说一定要用基本循环for(var i = 0; i < length; i++)
此处也引用一位大佬的博客,看了后受益匪浅https://m./article/?tdsourcetag=s_pctim_aiomsg
-
var x=[1];
-
for(var s in x){
-
alert(s);
-
};
按常理,如果Array是原生js类,上面语句应该只执行一次alert方法,且s为数组的索引0。但是,如果Array类被扩展了,多了一个toJSON方法,那么上面的语句将执行两次alert,第一次s为索引0,第二次s为方法名'toJSON'。
如果你设计的代码的逻辑以原生Array类为基准,在某一天你的同事在页面里面引用了一个第三方的JS库,这个库又恰好扩展了Array类,结果将难以想象,很有可能原来的代码逻辑将不再成立。