Javascript 函数作用域概念

Javascript function scope concepts

本文关键字:作用域 函数 Javascript      更新时间:2023-09-26

我正在阅读这本书"Javascript Ninja的秘密",其中大部分代码都是使用自定义断言来演示的。代码如下:

(function () {
    var queue = [],
        paused = false,
        results;
    this.test = function test(name, fn) {
        queue.push(function () {
            results = document.getElementById("results");
            results = assert(true, name).appendChild(
            document.createElement("ul"));
            fn();
        });
        runTest();
    };
    this.pause = function () {
        paused = true;
    };
    this.resume = function () {
        paused = false;
        setTimeout(runTest, 1);
    };
    function runTest() {
        if (!paused && queue.length) {
            queue.shift()();
            if (!paused) {
                resume();
            }
        }
    }
    this.assert = function assert(value, desc) {
        var li = document.createElement("li");
        li.className = value ? "pass" : "fail";
        li.appendChild(document.createTextNode(desc));
        if (results === undefined) results = document.getElementById("results");
        results.appendChild(li);
        if (!value) li.parentNode.parentNode.className = "fail";
        return li;
    };
})();

如您所见,这是一个自调用函数。

我一直在玩它,我只是无法理解的是,如果在同一标签之间,我这样做为什么:

<script type="text/javascript">
    ... previously shown code ...
    window.onload = function(){
       assert(true, "this works");
    };
</script>

然后,如果我只是这样做断言:

<script type="text/javascript">
    ... previously shown code ...
    assert(true, "this does not work");
</script>

当我尝试在不使用 window.onload 事件的情况下执行断言时,在断言方法的"results.appendChild(li)"行上收到错误"未捕获的类型错误:无法将方法'appendChild'调用为 null"。

非常感谢您的帮助。

元素

标记(带id="results")在代码运行时不会被解析,因此尝试使用getElementById获取它返回null,这反过来又使.appendChild失败。

当您将代码放入window.onload处理程序中时,它(处理程序函数中的代码)保证仅在加载窗口后运行,此时文档标记也会被完全解析并且元素可用。

或者,您可以简单地将脚本元素放在目标元素之后:

<ul id="results"></ul>
<script>
//your code
</script>
由于脚本元素位于目标元素

之后,因此在脚本运行时可以保证目标元素存在。

因为您是在呈现页面上的元素之前调用代码的。因此,当代码查找document.getElementById("results")时,它什么也找不到并返回 null。