我正在读这本书“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事件的情况下执行assert时,我在assert方法的“results.appendChild(li)”行中收到错误“Uncaught TypeError:无法调用方法'appendChild'为null”。
非常感谢你的帮助。
答案 0 :(得分:1)
因为您在呈现页面上的元素之前调用代码。因此,当代码查找document.getElementById("results")
时,它找不到任何内容并返回null。
答案 1 :(得分:1)
元素标记(使用id="results"
)在代码运行时不会被解析,因此尝试使用getElementById
获取它会返回null
,这会使{{1}失败。
当你将代码放在.appendChild
处理程序中时,它(处理函数内部的代码)保证只在加载窗口后运行,此时文档标记也被完全解析并且元素是可用的。
或者,您可以让脚本元素位于目标元素之后:
window.onload
因为脚本元素位于目标元素之后,所以目标元素在脚本运行时保证存在。