推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
mikej

看到一道面试题:<ul>有 10000 个<li>子元素,如何将这 10000 个<li>颠倒顺序。

  •  2
     
  •   mikej · Feb 19, 2014 · 40629 views
    This topic created in 4464 days ago, the information mentioned may be changed or developed.
    要求是效率尽量要高。不光是算法效率,还要考虑DOM元素操作的效率。大家有什么想法?
    还有就是遇到类似这种问题解题技巧?
    104 replies    2016-10-24 21:06:21 +08:00
    1  2  
    democ
        1
    democ  
       Feb 19, 2014   ❤️ 1
    1. 先复制一份 (不要插入到DOM中,频繁的操作DOM消耗资源是很大的)
    2. 对复制出的这份做操作. 方法是从最后一个开始拿插入到一个新的<ul>中 (这一步也不需要插入到DOM中)
    3. 将DOM中的<ul>更换为从新排序的<ul>

    有不合适的地方请楼下指出.
    learnshare
        2
    learnshare  
       Feb 19, 2014
    在内存中操作完成,然后插入到页面中
    kfll
        3
    kfll  
       Feb 19, 2014
    @democ 复制的实现复杂效率也不高,`cloneNode` 也不克隆事件
    @mikej 我的话会掐半用 `replaceChild` 首尾交换
    关系到 DOM 的优先考虑浏览器 API 再考虑算法..
    不一定对...
    bombless
        4
    bombless  
       Feb 19, 2014
    先remove掉ul,首尾交换上面的li再把ul插回去
    P233
        5
    P233  
       Feb 19, 2014   ❤️ 87
    ul {transform: rotate(180deg)}

    li {transform: rotate(180deg)}

    搞定
    tinyhill
        6
    tinyhill  
       Feb 19, 2014   ❤️ 1
    [].slice.call(nodeList).reverse(); 循环一次组成字符串插回 ul 节点
    chairuosen
        7
    chairuosen  
       Feb 19, 2014 via Android
    卧槽,楼上机智!!
    fakefish
        8
    fakefish  
       Feb 19, 2014
    fragementElement+=(lastchild--)
    parent.append(fragementElement)
    大概是这么个意思,把从最后的一个子元素开始复制到fragmentElement,组装完再一起插入原处
    fakefish
        9
    fakefish  
       Feb 19, 2014
    速度最快的肯定不能让dom在每次循环的时候有变化。
    blacktulip
        10
    blacktulip  
       Feb 19, 2014 via iPhone
    五楼正解
    sneezry
        11
    sneezry  
       Feb 19, 2014
    最快的方法我感觉是innerHTML
    sneezry
        12
    sneezry  
       Feb 19, 2014
    @P233 五楼你碉堡了。。。
    Sunyanzi
        13
    Sunyanzi  
       Feb 19, 2014
    只有我觉得只要简单的遍历一遍然后生成一个反向的大字符串写入 innerHTML 就好吗 ...

    这样的优点是快 ... 生成字符串绝对比任何的 DOM 操作来得都要高效 ...

    缺点是重新生成了列表 ... 所有原来元素上面的事件和属性都没了 ...

    如果要保持原来的元素 ... 大概也只能二分之后 replaceChild 了吧 ...
    clippit
        14
    clippit  
       Feb 20, 2014
    http://jsperf.com/reverse-li

    10000的时候确实用数组 reverse 比较快,但是如果 DOM 节点比较少的时候,反而是直接操作比较快呢
    catoncat
        15
    catoncat  
       Feb 20, 2014 via Android
    http://stackoverflow.com/questions/5530472/how-to-handle-10000-li-efficiently
    手机chrome测试,字符串和DOM操作响应差不多。
    democ
        16
    democ  
       Feb 20, 2014
    @clipplt 涨姿势了.数据说话.
    alay9999
        17
    alay9999  
       Feb 20, 2014
    五楼!五体投地!
    jprovim
        18
    jprovim  
       Feb 20, 2014
    @P233 非常好的Trick
    FrankFang128
        19
    FrankFang128  
       Feb 20, 2014 via Android
    这题哪看到的?
    mikej
        20
    mikej  
    OP
       Feb 20, 2014
    @clippit 佩服,真会解决问题
    @P233 太颠覆了。。。
    @fakefish 不错啊,思路挺清晰,代码也很简练。
    mikej
        21
    mikej  
    OP
       Feb 20, 2014
    @FrankFang128 知乎
    laoona
        22
    laoona  
       Feb 20, 2014
    给五楼跪了!
    FrankFang128
        23
    FrankFang128  
       Feb 20, 2014 via Android
    @mikej 这个问题是我出的。。。我只是随口一说的,想不到有人转到V2了 :)
    mengzhuo
        24
    mengzhuo  
       Feb 20, 2014
    5楼太机智了!怒赞一个!
    以后的倒序直接加class就over了,js代码又省了很多
    doublleft
        25
    doublleft  
       Feb 20, 2014
    @P233 好机制!!!!!!
    ccccccc
        26
    ccccccc  
       Feb 20, 2014
    可以用css3 flex order改变排序
    geew
        27
    geew  
       Feb 20, 2014
    5楼碉堡了, 10086个怒赞
    paloalto
        28
    paloalto  
       Feb 20, 2014
    5楼太颠覆了!!! !
    RoshanWu
        29
    RoshanWu  
       Feb 20, 2014
    我是来看5楼的,啊,真是个机智的骚年
    EPr2hh6LADQWqRVH
        30
    EPr2hh6LADQWqRVH  
       Feb 20, 2014
    次奥怒赞5楼
    shiye515
        31
    shiye515  
       Feb 20, 2014
    @P233
    learnshare
        32
    learnshare  
       Feb 20, 2014
    五楼... 给跪了
    January
        33
    January  
       Feb 20, 2014
    五楼笑死我了
    atian25
        34
    atian25  
       Feb 20, 2014   ❤️ 1
    赞5楼...
    还有个:
    <ol reversed>
    <li>list item one</li>
    <li>list item two</li>
    <li>list item three</li>
    <li>list item four</li>
    <li>list item five</li>
    </ol>
    http://www.w3schools.com/tags/att_ol_reversed.asp
    mikej
        35
    mikej  
    OP
       Feb 20, 2014
    @FrankFang128 是吗?呵呵,没想到还能在这里遇到。。
    iamjs
        36
    iamjs  
       Feb 20, 2014
    5楼。。直接面试官崩溃的节奏。。
    Sight4
        37
    Sight4  
       Feb 20, 2014
    @P233 神回复!!
    shiny
        38
    shiny  
    PRO
       Feb 20, 2014
    5楼是嘲弄面试官呀
    kevinroot
        39
    kevinroot  
       Feb 20, 2014
    @P233 碉堡~样式大神
    honk
        40
    honk  
       Feb 20, 2014
    @P233 不得不贊!!
    refresh
        41
    refresh  
       Feb 20, 2014
    @P233 不是css3不支持吧
    spheee
        42
    spheee  
       Feb 20, 2014
    @P233 太厉害了
    jacob
        43
    jacob  
       Feb 20, 2014
    @P233 css对js强力逆袭啊。
    Ellison
        44
    Ellison  
       Feb 20, 2014
    5楼怒赞...
    heckthisplace
        45
    heckthisplace  
       Feb 20, 2014
    热情的转到知乎。
    unnya
        46
    unnya  
       Feb 20, 2014
    @P233 忍不住点个赞
    aisensiy
        47
    aisensiy  
       Feb 20, 2014
    @sneezry 我觉得也是
    P233
        48
    P233  
       Feb 20, 2014
    @refresh IE9+ 都支持
    P233
        49
    P233  
       Feb 20, 2014
    感谢大家!
    tonitech
        50
    tonitech  
       Feb 20, 2014
    @P233 厉害厉害!!!哈哈哈!
    shiniv
        51
    shiniv  
       Feb 20, 2014
    怒赞
    sanddudu
        52
    sanddudu  
       Feb 20, 2014
    @atian25 这个只颠倒序号。所以只支持有序列表,题目用的是无序的
    zztczcx
        53
    zztczcx  
       Feb 20, 2014
    我是来看5楼的
    princexu
        54
    princexu  
       Feb 20, 2014
    5楼碉堡了....
    jieorlin
        55
    jieorlin  
       Feb 20, 2014
    ### fdsafdfdsf
    jieorlin
        56
    jieorlin  
       Feb 20, 2014   ❤️ 1
    lichgo
        58
    lichgo  
       Feb 20, 2014
    5楼的解法让我想到一道经典算法题:
    Reverse words in a sentence: "I am a geek" => "geek a am I"。

    另外,应用CSS在10000个DOM元素上,每个元素都要重画(repaint)吧?效率如何?会比JS更高?
    lnehe
        59
    lnehe  
       Feb 20, 2014
    把显示器倒过来。。。。
    ericls
        60
    ericls  
       Feb 20, 2014
    5 楼碉堡了!
    shyrz
        61
    shyrz  
       Feb 20, 2014
    我是来围观5楼的,机智的骚年~
    ccming
        62
    ccming  
       Feb 20, 2014
    好腻害
    MingZhe
        63
    MingZhe  
       Feb 20, 2014
    由于不是搞前端的,对五楼的说法刚开始没注意。没想到下面这么多人赞,果断去查。。。确实碉堡了。给赞一个
    iamjs
        64
    iamjs  
       Feb 20, 2014
    @lichgo 难说 因为几乎不可能在真实的场景中遇到。典型的面试题目。
    如果我是面试官。给我一个js转换方法和这个答案。我想后者更能给考官留下深刻印象吧。。
    FrankFang128
        65
    FrankFang128  
       Feb 20, 2014
    @iamjs 大家喜欢抖机灵的答案
    RIcter
        66
    RIcter  
       Feb 21, 2014
    @FrankFang128 不过不失为一个好办法。
    donkeylucky
        67
    donkeylucky  
       Feb 21, 2014
    5楼的 大大的机智
    andy12530
        68
    andy12530  
       Feb 21, 2014
    如果不考虑普通低级浏览器,5楼的办法是最简单好用的。
    qazwsxedc
        69
    qazwsxedc  
       Feb 21, 2014
    围观5楼
    shiye515
        70
    shiye515  
       Feb 21, 2014
    @lichgo js添加元素不也要重绘么,还要加上操作dom的时间
    hilenlai
        71
    hilenlai  
       Feb 21, 2014
    5楼太机智了!!
    siyang1982
        72
    siyang1982  
    PRO
       Feb 21, 2014
    在本页玩了一下:`$('#Main .box:eq(1), #Main .box:eq(1) > *').css('transform', 'rotate(180deg)')`
    fen
        73
    fen  
       Feb 21, 2014
    @P233 5 楼无敌
    YufunHe
        74
    YufunHe  
       Feb 21, 2014
    围观五楼
    ffts
        75
    ffts  
       Feb 21, 2014
    卧槽,看了演示之后才知道5楼的想法多NB
    lidonghao
        76
    lidonghao  
       Feb 21, 2014
    5楼的答案 面试官也不能说错啊 哈哈
    airski
        77
    airski  
       Feb 21, 2014
    大赞机智的5楼。
    lijsh
        78
    lijsh  
       Feb 21, 2014
    HeyMan
        79
    HeyMan  
       Feb 21, 2014
    想象力真强!
    flynngao
        80
    flynngao  
       Feb 21, 2014
    5楼鸡汁超越人类
    adam
        81
    adam  
       Feb 21, 2014
    可以作为一条面试题~~
    est
        82
    est  
       Feb 21, 2014
    @siyang1982 卧槽居然成功了
    rekey
        83
    rekey  
       Feb 21, 2014
    特地赶来赞5楼的.
    Keinez
        84
    Keinez  
       Feb 21, 2014 via Android
    @P233 五楼已经颠覆我对CSS3的认知
    zzNucker
        85
    zzNucker  
       Feb 21, 2014
    @lichgo CSS3动画是不需要repaint的。
    FrankFang128
        86
    FrankFang128  
       Feb 21, 2014 via Android
    @RIcter 充分说明前端思维角度和后台是不同的
    sampeng
        87
    sampeng  
       Feb 21, 2014
    由于我带前端团队。。
    这个题目,我刚看到。第一反应是,这是个好题。。第二反应,取出来。用算法,然后插入dom。这个是常规的。第三反应,css是控制显示的。如果用css控制呢?我不懂css。所以,我会先用个第二种方式上线,因为开发快。写代码,不一定要精细到极致,一切都是可改的。完全可以满足产品需求,回头再改(如果记得的话)。然后再找时候去网上找找css有没办法。。。收工。
    如果面试的用上面的这个思路来回答,我会直接弄进来。。赶紧去给我去干活
    otakustay
        88
    otakustay  
       Feb 21, 2014
    @zzNucker 你确定?不需要relayout/reflow我知道,repaint也不需要那屏幕上的东西是如何改变的?CSS3的translate3D顶多也就是让浏览器支持图层缓存,不用repaint感觉有点太厉害了啊
    otakustay
        89
    otakustay  
       Feb 21, 2014
    @lichgo 效率比JS高那是轻轻松松,JS这么做一是DOM结构变化的计算,二是函数调用的损耗(JS<->DOM不是一般的JS函数调用,往往要走一个代理或者序列化),三是引起重布局的损耗,四是有没有浏览器做GPU加速之类的优化的区别
    zzNucker
        90
    zzNucker  
       Feb 21, 2014
    @otakustay 唔,我这样表达确实不太对,是不做传统意义上的那种非常耗资源的repaint,就是整个renderlayer tree的重绘。 而用CSS Translate3D这种的话,在开启了硬件合成加速以后会直接在GPU RAM里作为texture改变,就相当于改变的部分很少,而且基本不占用CPU资源。
    zzNucker
        91
    zzNucker  
       Feb 21, 2014
    刚发现chrome新版取消了windows下的强制合成的选项。
    zzNucker
        92
    zzNucker  
       Feb 21, 2014
    难道已经默认启用了。
    P233
        93
    P233  
       Feb 21, 2014
    @lichgo
    @shiye515
    @otakustay
    @zzNucker

    做了个简单的测试(可能并不严谨),Chrome 下 10000 个 li 元素,page paint time 在 3.4ms - 4.7ms 左右;使用 ul,li {transform: rotate(180deg)} 反转后(不会开启 GPU 加速),骤增到 13.2ms - 16.6ms 左右;translateZ(0) 强制开启 GPU 加速后,page paint time 只有 1.5ms - 1.8ms
    otakustay
        94
    otakustay  
       Feb 22, 2014
    @P233 感谢实验,理论上translateZ因为有贴图缓存支持肯定够快,DOM操作可能会因为li中的内容复杂度有很大的区别,而transform我理解应该和内容复杂度关系不呈线性
    mikej
        95
    mikej  
    OP
       Feb 22, 2014
    @otakustay
    @zzNucker
    @P233
    研究得够深!都是前端牛人啊。
    lygmqkl
        96
    lygmqkl  
       Feb 22, 2014
    做了6年后端了,说实话 五楼的想法让我眼前一亮,web 不只是数据。 哈哈
    P233
        97
    P233  
       Feb 22, 2014
    @otakustay 应该是这样的,贴两张测试截图





    开启 GPU 加速后,recalculate 时间竟然增加了很多,但 paint time 毫无疑问减少了
    iLluSioN
        98
    iLluSioN  
       Feb 22, 2014
    ……给五楼跪
    jabbany
        99
    jabbany  
       Feb 23, 2014
    太机智了.......
    run2
        100
    run2  
       Feb 26, 2014
    @siyang1982 也是直接论坛最近回复在前的解决方法
    1  2  
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3511 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 677ms · UTC 10:59 · PVG 18:59 · LAX 03:59 · JFK 06:59
    ♥ Do have faith in what you're doing.