初学js,最近碰到一个比较困惑的问题,就是在页面加载后执行的命令是否都需要放进onload事件中? 我用下面这种自执行函数的形式,然后把js文件放到</body>标签的上面一行似乎也可以达成同样的效果。
</body>
(function() { //要执行的命令 })();
个人的理解是,onload事件是在页面资源(包括图片、css、Js等)完全加载后才发生的,那是否不涉及操作外部资源的情况下,完全可以用自执行函数来代替onload事件?
认证高级PHP讲师
这个应该根据需求而定,完全替代肯定是不可能的。 如果你的需求是页面载入后即执行,那么按题主的方式写个位于底部的自执行函数自然可以达到效果。
但假设我的需求是对页面中一个 IMG 元素的 height 和 width 属性进行操作,你的自执行函数就有可能失效了,因为你没法判断图像是否已经完全载入,而如果使用 onload 方法时,则表示页面内的资源都已经载入,此时执行内部的代码操作图像元素的宽高一定是没有问题的。
IMG
height
width
onload
即使是 jQuery 封装的 $(document).ready() 方法也不能说取代 onload 方法,简单的立即执行函数又怎么可能做到呢?:)
jQuery
$(document).ready()
看了上面的答案,还是没明白,题主需要弄清楚一个概念:
JS具有阻塞特性,当浏览器在执行js代码时,不能同时做其它事情,即<script>每次出现都会让页面等待脚本的解析和执行(不论JS是内嵌的还是外链的),JS代码执行完成后,才继续渲染页面。 所有<script>应该尽可能放到<body>的底部,以减少对页面下载的影响。
找了下资料:
window.onload需要当页面全部加载完成,包括图片、flash等富媒体; DOMReady只需要判断页面内所有的DOM节点是否已经全部生成,至于节点中的内容是否已经加载完成,它并不关心。 因此DOMready触发事件的响应速度比window.onload更快,更迅速。
DOM Ready 调研结论
setTimeout设置的函数, 会在readyState为complete时触发, 但是触发时间点是在图片资源加载完毕后. readyState为interactive时, DOM结构并没有稳定, 此时依然会有脚本修改DOM元素. readyState为complete时, 图片已经加载完毕, 实验中对图片加载设置了延时.所以complete虽然在window.onload前执行, 但是还是太晚. 外部script:如果将此script放在页面上方, 则无法稳定触发. 并且触发时DOM结构依然可能发生变化. 内部script:与外部script同样的问题, 触发的时间过早. doScroll: doScroll通过时readyState可能为interactive, 也可能为complete. 但是一定会在DOM结构稳定后, 图片加载完毕前执行. 所以可以看出, 目前的setTimeout方法, 外部script和内部script方法, 都是存在错误的.应该说这些方法不能安全可靠的实现DomReady事件. 而单纯使用readyState属性是无法判断出Dom Ready事件的. interactive状态过早(DOM没有稳定), complete状态过晚(图片加载完毕). jQuery实现中使用的doScroll方法是目前唯一可用的方法. window.onload 这时图片flash等资源都加载完毕
setTimeout设置的函数, 会在readyState为complete时触发, 但是触发时间点是在图片资源加载完毕后.
readyState为interactive时, DOM结构并没有稳定, 此时依然会有脚本修改DOM元素. readyState为complete时, 图片已经加载完毕, 实验中对图片加载设置了延时.所以complete虽然在window.onload前执行, 但是还是太晚.
外部script:如果将此script放在页面上方, 则无法稳定触发. 并且触发时DOM结构依然可能发生变化. 内部script:与外部script同样的问题, 触发的时间过早.
doScroll: doScroll通过时readyState可能为interactive, 也可能为complete. 但是一定会在DOM结构稳定后, 图片加载完毕前执行.
所以可以看出, 目前的setTimeout方法, 外部script和内部script方法, 都是存在错误的.应该说这些方法不能安全可靠的实现DomReady事件.
而单纯使用readyState属性是无法判断出Dom Ready事件的. interactive状态过早(DOM没有稳定), complete状态过晚(图片加载完毕).
jQuery实现中使用的doScroll方法是目前唯一可用的方法. window.onload 这时图片flash等资源都加载完毕
当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(node)上引用了CSS或者IMAGE,就会再发1个request去请求CSS或image,然后继续执行下面的转换,而不需要等待request的返回,当request返回后,只需要把返回的内容放入到DOM树中对应的位置就OK。但当引用了JS的时候,浏览器发送1个js request就会一直等待该request的返回。因为浏览器需要1个稳定的DOM树结构,而JS中很有可能有代码直接改变了DOM树结构,比如使用document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以就会阻塞其他的下载和呈现.
不能, 因为自执行函数是立刻运行的. 即使 DOM 没有加载完成.
错位典例:http://segmentfault.com/q/1010000000441480
只看题目不看描述的下场 ↑
处理脚本和样式表的顺序是同步的.
如果放在 </body> 之前这和浏览器中的 DOMContentLoaded 事件 类似. 仅在 前面 的 DOM 树加载完成后执行, 并不包括 css / image / iframe...
DOMContentLoaded
所以答案是可以的, 之前的答案也提到了. 无地自容 还有一点它 不能 替代 onload , 因为 onload 指的是网页完全的加载.
谢谢 @公子 的提醒.onload 一般泛指的是 DOM 内的完全加載, 上面描述的是仅仅是 window.onload 这一种情况.
window.onload
这俩概念完全就不是一回事儿。就好像雷峰塔和巴基斯坦,有啥关系呢?
自执行函数,免去了命名再执行的繁琐,反正用一次就不管了。 可是onload是事件啊,就好像是,我狠狠掐了你一下,你才会疼的哇哇叫。
那么,你觉得,我说的特定事件跟匿名函数,有啥关系?
特定事件
匿名函数
如果需要执行的代码不依赖于DOM的样式之类的,当然可以替代啦。
此外,还有一个DOM ready事件,不同浏览器实现不同,jQuery有一个封装好的方法是
$(document).ready(fun)
三者的执行先后:
【写在</body>前】 先于 【DOM ready事件】 先于 【Window onload事件】
这个应该根据需求而定,完全替代肯定是不可能的。
如果你的需求是页面载入后即执行,那么按题主的方式写个位于底部的自执行函数自然可以达到效果。
但假设我的需求是对页面中一个
IMG
元素的height
和width
属性进行操作,你的自执行函数就有可能失效了,因为你没法判断图像是否已经完全载入,而如果使用onload
方法时,则表示页面内的资源都已经载入,此时执行内部的代码操作图像元素的宽高一定是没有问题的。即使是
jQuery
封装的$(document).ready()
方法也不能说取代onload
方法,简单的立即执行函数又怎么可能做到呢?:)看了上面的答案,还是没明白,题主需要弄清楚一个概念:
找了下资料:
window.onload需要当页面全部加载完成,包括图片、flash等富媒体;
DOMReady只需要判断页面内所有的DOM节点是否已经全部生成,至于节点中的内容是否已经加载完成,它并不关心。
因此DOMready触发事件的响应速度比window.onload更快,更迅速。
DOM Ready 调研结论
当浏览器从服务器接收到了HTML文档,并把HTML在内存中转换成DOM树,在转换的过程中如果发现某个节点(node)上引用了CSS或者IMAGE,就会再发1个request去请求CSS或image,然后继续执行下面的转换,而不需要等待request的返回,当request返回后,只需要把返回的内容放入到DOM树中对应的位置就OK。但当引用了JS的时候,浏览器发送1个js request就会一直等待该request的返回。因为浏览器需要1个稳定的DOM树结构,而JS中很有可能有代码直接改变了DOM树结构,比如使用document.write 或 appendChild,甚至是直接使用的location.href进行跳转,浏览器为了防止出现JS修改DOM树,需要重新构建DOM树的情况,所以就会阻塞其他的下载和呈现.
不能, 因为自执行函数是立刻运行的. 即使 DOM 没有加载完成.
错位典例:
http://segmentfault.com/q/1010000000441480
只看题目不看描述的下场 ↑
处理脚本和样式表的顺序是同步的.
如果放在
</body>
之前这和浏览器中的DOMContentLoaded
事件 类似.仅在 前面 的 DOM 树加载完成后执行, 并不包括 css / image / iframe...
所以答案是可以的, 之前的答案也提到了.
无地自容还有一点它 不能 替代
onload
, 因为onload
指的是网页完全的加载.谢谢 @公子 的提醒.
onload
一般泛指的是 DOM 内的完全加載, 上面描述的是仅仅是window.onload
这一种情况.这俩概念完全就不是一回事儿。就好像雷峰塔和巴基斯坦,有啥关系呢?
自执行函数,免去了命名再执行的繁琐,反正用一次就不管了。
可是
onload
是事件啊,就好像是,我狠狠掐了你一下,你才会疼的哇哇叫。那么,你觉得,我说的
特定事件
跟匿名函数
,有啥关系?如果需要执行的代码不依赖于DOM的样式之类的,当然可以替代啦。
此外,还有一个DOM ready事件,不同浏览器实现不同,jQuery有一个封装好的方法是
三者的执行先后:
【写在</body>前】 先于 【DOM ready事件】 先于 【Window onload事件】