Dive into downloads blocked by script

在Yahoo的一篇文章里看到如下描述:

The problem caused by scripts is that they block parallel downloads. The HTTP/1.1 specificationsuggests that browsers download no more than two components in parallel per hostname. If you serve your images from multiple hostnames, you can get more than two downloads to occur in parallel. While a script is downloading, however, the browser won’t start any other downloads, even on different hostnames.

In some situations it’s not easy to move scripts to the bottom. If, for example, the script usesdocument.write to insert part of the page’s content, it can’t be moved lower in the page. There might also be scoping issues. In many cases, there are ways to workaround these situations.

An alternative suggestion that often comes up is to use deferred scripts. The DEFER attribute indicates that the script does not contain document.write, and is a clue to browsers that they can continue rendering. Unfortunately, Firefox doesn’t support the DEFER attribute. In Internet Explorer, the script may be deferred, but not as much as desired. If a script can be deferred, it can also be moved to the bottom of the page. That will make your web pages load faster.

看到上述加粗的一句话,说明浏览器下载script的过程一定是单线程的,如果某个script的下载需要一段比较长的时间,那么整个页面的加载可能就会被大大拖慢。为什么不能并行下载呢?其中一个原因可能是如果后一个script需要使用前一个script的结果的话,那么最简单的解决方法是硬性规定下载顺序。

除了这点外,原文还说到一个要点,就是可以在JavaScript中加一个叫DEFER的属性。使用这个属性的前提有两点:

  1. 这个script里不能包含有立即改变网页内容的语句,例如document.write
  2. 不要script中包括任何立即执行脚本要使用的全局变量或者函数

defer型script具体写法是这样的:

<script language="javascript" type="text/javascript" defer>

<script type="text/javascript" defer="defer">

遗憾的是Firefox不支持此属性,而且IE在里也不是如你想象中解析这个属性,我在另一篇文章中看到如下描述:

Explorer 4+ on Windows has slightly changed the meaning ofdefer. Any code inside deferred script tags is only executed when the page has been parsed entirely.

那么在IE里就相当于window.onload了,也可能是这个原因,这个鸡肋的属性没有被广泛地应用。

到目前为止,我搜索到的普片适用的解决方法只有两个,一个是使用HTML5的asyncs属性,另一个是如Yahoo那篇文章所说,直接把script放在文档尾部

一个成功的在支持HTML5浏览器上实现并行下载script的例子是:

(function() {
    var s = document.createElement('script');
    s.type = 'text/javascript';
    s.async = true;
    s.src = 'http://yourdomain.com/script.js';
    var x = document.getElementsByTagName('script')[0];
    x.parentNode.insertBefore(s, x);
})();

关于script三种加载方式的时间顺序图:普通方式,使用defer属性,使用HTML5的async属性

普通方式:          也就是单线程方式
defer属性方式:简单地把执行时间推迟到HTML Parser完毕
async属性:      下载的同时可以进行HTML Parser的工作,而且当script下载完毕以后不用等待便可以立即执行

UPDATE: 在Firefox 3.6.13和IE8上只验证了不能从同一个IP中同时下载两个文件,但可以从不同IP中同时下载不同的scripts.

参考文章:
http://developer.yahoo.com/performance/rules.html
http://www.itlearner.com/article/4313
http://www.quirksmode.org/js/placejs.html
http://techie-buzz.com/webmaster-tips/load-banner-ads-after-page-loads.html
http://peter.sh/experiments/asynchronous-and-deferred-javascript-execution-explained/

Tetris Elements, “This is bad Tetris. It’s hateful Tetris.”

我们玩俄罗斯方块的时候一般都是电脑随机选择下一个方块,那如果电脑不是随机选择,而是专门用一个算法选取对你当前最不利的一个方块,你能坚持多久?

在游戏中你会遇到非常多的“S”方块,作者说,如果你能转变S对你的不利因素,其他的方块就会出现,幸运的话你还可能看到所有的7种方块,包括那种很有用的T方块。

要深入研究the concept of “a game of Tetris which always gives you the worst possible pieces”,请看这里

我目前最高纪录是消了4行,作者说他的最高纪录是消5行,你呢?

Javascript for loop, for and for…in

有兴趣的朋友可以尝试一下下面的执行结果:

for…in loop:

var characterArr = new Array();

characterArr[0] = "a";
characterArr[5] = "b";
characterArr[10] = "c";

for (index in characterArr) {
    characterArr[parseInt(index) + 2] = "new character";
    alert("index=" + index + "  value=" + characterArr[index]);
    delete characterArr[5];
}
alert("separate here!");
for (index in characterArr) {
    alert("index=" + index + "  value=" + characterArr[index]);
}

以下代码尝试前要做好心理准备,我不是恶作剧…
for loop:

var characterArr = new Array();

characterArr[0] = "a";
characterArr[5] = "b";
characterArr[10] = "c";

for (var index = 0; index <  characterArr.length; index++) {
    characterArr[index + 2] = "new character";
    alert("index=" + index + "  value=" + characterArr[index]);
}

我的结论:for…in loop循环的只是对象的一个副本.而for loop循环的是对象本身.