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

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

    li {transform: rotate(180deg)}

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

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

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

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

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

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





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