题主中午在 “在外部js里实现等页面加载完成了再执行脚本,即不用window.onload,也不将<script>块放在底部,也不使用库”这个问题下有人提供了一段代码,问题链接:http://.com/q/1010000002672728。题主对其如何实现window.load的类似功能进行了探究,但是理解不了,有两个疑惑,先把原问题@HJin_me 大大提供的代码贴出来
var isReady = false;
var readyList = [];
function ready(fn) {
if (isReady) {
setTimeout(function () {
fn()
}, 0);
return;
}
readyList.push(fn);
}
function setReady() {
if (isReady) {
return;
}
isReady = true;
for (var i = 0, n = readyList.length; i < n; i++) {
readyList[i]();
}
readyList.length = 0;
}
(function () {
if (document.readyState === 'complete') {
setTimeout(setReady, 0);
} else {
document.addEventListener('DOMContentLoaded', setReady);
window.addEventListener('load', setReady);
}
}());
题主小白,知道最后是一个自执行函数,可是觉得最后一个function自执行函数外的括号多余,删除了,删除之后,无法起到等页面加载完成再执行的作用了,这是问题一。
第二,题主将setReady函数传参fn,然后不用队列,直接fn(),html也做相应变化代码如下:
var isReady = false;
var readyList = [];
function ready(fn) {
if (isReady) {
setTimeout(function () {
fn()
}, 0);
return;
}
readyList.push(fn);
}
function setReady(fn) {
if (isReady) {
return;
}
isReady = true;
fn();
}
(function () {
if (document.readyState === 'complete') {
setTimeout(setReady, 0);
} else {
document.addEventListener('DOMContentLoaded', setReady);
window.addEventListener('load', setReady);
}
}());
html代码如下:
<html>
<head>
<script type="text/javascript" src="http://localhost/everywhere.js"></script>
<script type="text/javascript">
function ask(){alert(document.getElementById("hehe"))}
setReady(ask);
//ready();
</script>
</head>
<body>
<p id="hehe">test</p>
</body>
</html>
结果alert出来null而不是object,题主对这两个问题百思不得其解。
先说第一个问题:
(function (){}());
(function (){})();
形如以上两种的其实是叫“立即执行的函数表达式”
为什么是表达式呢?
JavaScript规定,()
括号中只能放表达式,如果不是表达式的,会被当做表达式来解析。
你看到的外层的那对小()
括号是告诉解析器按表达式来解析。
为什么会立即执行呢?
举个栗子:
var show = function(){
console.log('1');
}
我们声明了一个函数,现在调用它
show();
在函数名的后面加了对()
括号,然后函数就执行了。
现在同理,我们通过小()
在声明的同时执行函数,就成了“立即执行的函数表达式”。