我想实现的是类名点击切换效果,具体的功能实现没有问题,只是在一开始的 window.onload 有一些疑惑。HTML代码为:
HTML代码:
<div id="del" class="del">
<dl>
<dt>配送类型:</dt>
<dd class="selected" value=0><a href="#">全部</a></dd>
<dd value=1><a href="#">京东配送</a></dd>
<dd value=2><a href="#">第三方配送</a></dd>
</dl>
</div>
具体代码见 demo
该 demo 是能够正常实现的,在本地实现的时候,js文件是在<body>标签内最后引入的。现在的问题是,如果改变 window.onload 的写法就会报错,不报错代码如下:
JS代码:
window.onload = function(){
del();
};
报错代码如下:(报错为:Uncaught TypeError: Cannot read property 'length' of undefined, 即 dd 为 undefined )
JS代码:
window.onload = del();//即去掉外面包裹的匿名函数
以上情况,都是当将该语句放在脚本文件的开头处。
经测试,如果将上面会报错的代码语句,放置在脚本文件最后的位置,不会报错。
所以想问一下,其中的问题在哪里?
把del()的()去掉
window.onload = del;
其1 你给 window.onload
赋值的是 del
这个函数的返回值.
其2是, 在del
这个函数被调用时 dd
的值是 undefined
;
具体原因为 变量作用域提升
, 参考文章: http://bonsaiden.github.io/JavaScript-Garden/zh/#function.scopes
参考代码:
<script type="text/javascript">
xx();//undefined
var a = 1;
xx();//1
function xx(){
alert(a);
}
</script>
所以在函数 del
中使用 dd.length
时, 就会报 Uncaught TypeError: Cannot read property 'length' of undefined
, 因为此时 dd
的值是 undefined
.
其3, 你的Demo中, js
代码位于 HTML 代码的后面, 所以:
1. 你可以不用写 window.onload
, 只用把 del();
的调用放在 var dd= xxx
这行的后面就可以了.
2. 如果将来这段js
代码在 HTML代码 的前面, 你目前Demo
中的代码还是错误的, 因为 var dd=xxx
在执行的时候, 它要找的那个DOM节点还是没生出来,错误信息应该是: TypeError: Cannot read property 'getElementsByTagName' of null
.
所以根据以上的这些信息,如果要写出正确的代码,可以有以下几种办法:
1. 把你的JS放在 </body>
之前和js
中要使用到的DOM节点之后.
2. 把对del
这个函数的调用放在 window.onload
中.
可以有以下两种方法:
window.onload = del;
window.onload = function(){del();}
- 把对
dd
的赋值放在 你的del
函数内部,作用域为全局变量,因为你的show
方法,也要使用到dd
, 或者再套个函数, 让dd
的作用域只对del
和show
可见.
===============================
建议改后的代码:
<!DOCTYPE html>
<html>
<head>
<style>
dd a{
color: #000;
}
dd.selected a{
color: red;
}
</style>
</head>
<body>
<div id="del" class="del">
<dl>
<dt>配送类型:</dt>
<dd class="selected" value=0><a href="#">全部</a></dd>
<dd value=1><a href="#">京东配送</a></dd>
<dd value=2><a href="#">第三方配送</a></dd>
</dl>
</div>
<script type='text/javascript'>
(function(target, cls){
var dd = document.getElementById(target), index = 0;
if(dd === null){
return;
}
dd = dd.getElementsByTagName('dd');
//循环给每一个绑定事件
for (var i = dd.length; i--;) {
//绑定onclick事件
dd[i].onclick = show;
//查找当前选中的那个
if(dd[i].className === 'selected'){
index = i;
}
}
function show(){
//当前对应的那个
var num = this.getAttribute('value') * 1;
this.className = cls;
dd[index].className = null;
index = num;
return false;
}
})('del', 'selected');
</script>
</body>
</html>
window.onload = funcRef;
这里 funcRef 函数引用。应该 window.onload = del
参考:
window.onload
从报的错误来看,是你的函数在获取dom元素之前被调用了,所以获取不到你的dd,所以dd是undefined,所以undefined没有length。
那么,如果你将js代码放在</body>之前,那么久不需要window.onload了。