首页 > window.onload代码不使用匿名函数包裹报错

window.onload代码不使用匿名函数包裹报错

我想实现的是类名点击切换效果,具体的功能实现没有问题,只是在一开始的 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();}
  1. 把对 dd 的赋值放在 你的del函数内部,作用域为全局变量,因为你的show方法,也要使用到dd, 或者再套个函数, 让dd的作用域只对 delshow可见.

===============================
建议改后的代码:

<!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了。

【热门文章】
【热门文章】