Javascript 为什么在将每个结果添加到列表之前,此循环要等待完成?w/JSFiddle

Javascript 为什么在将每个结果添加到列表之前,此循环要等待完成?w/JSFiddle,javascript,while-loop,rendering,Javascript,While Loop,Rendering,我做了一个非常简单的循环来演示我的问题: var listMaker = function() { document.getElementById('list').innerHTML = ""; var i = 1; while (i < 150) { document.getElementById('list').innerHTML += "<li>" + i + "</li>"; i++;

我做了一个非常简单的循环来演示我的问题:

  var listMaker = function() {
     document.getElementById('list').innerHTML = "";
     var i = 1;
     while (i < 150) {
        document.getElementById('list').innerHTML += "<li>" + i + "</li>";
        i++;
    }
};​
var listMaker=function(){
document.getElementById('list').innerHTML=“”;
var i=1;
而(i<150){
document.getElementById('list').innerHTML+=“
  • ”+i+”
  • ”; i++; } };​
    我认为这个函数将立即开始打印到列表中,一次添加一个数字

    var listMaker = function() {
        var list = document.getElementById('list'),
            i = 1;
        function doNext() {
            if (i < 150){
                list.innerHTML += "<li>" + i + "</li>";
                setTimeout(doNext, 100);
                i++;
            }
        }
        doNext();
    };​
    
    相反,它会等待完成,然后推送包含150个数字的完整列表


    浏览器运行JS并在同一线程上进行页面更新。这意味着在函数运行时,它不会更新显示。因此,在某种意义上,一次只添加一个项目,但在添加完所有项目后重新绘制显示之前,您无法看到这些项目

    从用户的角度来看,浏览器将被锁定,直到JS完成,所以长时间运行循环是个坏主意

    您可以使用
    setTimeout()
    重写循环,然后可以看到它们一次出现在页面上

    var listMaker = function() {
        var list = document.getElementById('list'),
            i = 1;
        function doNext() {
            if (i < 150){
                list.innerHTML += "<li>" + i + "</li>";
                setTimeout(doNext, 100);
                i++;
            }
        }
        doNext();
    };​
    
    var listMaker=function(){
    var list=document.getElementById('list'),
    i=1;
    函数doNext(){
    如果(i<150){
    list.innerHTML+=“
  • ”+i+“
  • ”; 设置超时(doNext,100); i++; } } doNext(); };​
    演示:

    将函数的执行排队等待以后,允许当前函数完成,进而允许浏览器重新绘制屏幕

    setTimeout()
    的第二个参数是以毫秒为单位的延迟-显然,您已经根据您所追求的效果进行了适当的设置。

    以下是我的尝试(基本上与第一个答案相同,尽管是独立得出的,但使用了立即调用的匿名函数(IIAF):

    (函数(){
    var i=1,
    list=document.getElementById('list');
    list.innerHTML=“”;
    函数addToList(){
    如果(i<16){
    list.innerHTML+=“
  • ”+i+“
  • ”; i++; setTimeout(addToList,300); } } addToList(); })();​
    既然它发生得如此之快,你怎么知道它不是“一次添加一项”?当然,它是在一个循环中。很抱歉,这可能是一个太快的循环,但事实上它不是。如果要将I的最大值更改为10000..它实际上有很大的延迟!它会立即添加列表。请在调试中查看mode@Passerby我就是这么想的——我甚至在这么早以前就回答了,然后我就被骂了。谢谢你…我有史以来第一个关于StackOverflow的问题和答案!不客气。欢迎加入。进一步回答我的问题,请注意,即使浏览器在运行一个JS块时重新绘制,一个只有150次迭代的循环也会非常快,你无论如何都看不到单个项目…nnn分配document.getElemen有什么好处tById到循环外部的变量?存储
    document.getElementById()的结果
    在变量中更有效,因为它使浏览器不必在每次迭代中再次查找元素。在这种情况下,这无关紧要,但却是一个好习惯。想象一下,如果每次都要在元素上设置其他四个属性:即使忽略性能,只要重复变量,代码也会更整洁ble名称四次,而不是重复
    document.getElementById()
    四次。您愿意解释IIAF吗?这真是太有用了……我真是太感谢你们了!“匿名”表示它没有名称(请注意,没有名称-它只有调用“(函数(){…})()。它会立即被调用,因为在我将函数括在括号中之后,我可以使用normal()invocation language元素调用函数以使其立即运行。另一种更常见的方法是命名后调用函数,如函数foo(){…};foo();