Discuss / JavaScript / 这个练习有点诡异

这个练习有点诡异

Topic source

A牧羊小童

#1 Created at ... [Delete] [Delete and Lock User]

下面的代码,是可以通过测试的,这个逻辑可以理解。

// sort list:

var li = document.getElementById('test-list');

var liAry = Array.from(li.children).sort((x,y)=>{

return x.innerText > y.innerText? 1:-1;

});

/*请注意这一行*/

li.innerHTML = '';

for(var i=0;i<liAry.length;i++){

console.log(liAry[i].innerText);

l = document.createElement('li');

l.className = 'lang';

l.innerText = liAry[i].innerText;

li.appendChild(l);

}

但是上面的代码中,如果把 **li.innerHTML = '';**这一行移除,就不正常了,运行之后原来的元素还在,就变成10个 li 元素了。

这个也能理解,毕竟没有清空 **li** 对象直接进行appendChild操作,是会保留原来的元素的。

但是,诡异的来了,下面的代码,没有清空 **li** 对象,直接在forEach中进行了 appendChild,但为什么没有保留原来的元素呢?

// sort list:

var li = document.getElementById('test-list');

Array.from(li.children).sort((x,y)=>{

     if(x.innerText> y.innerText) 

return 1

     else 

return -1 

}).forEach(a => li.appendChild(a))

本人js小白,无法理解上面的代码区别,请懂的同学回复解释下。

FLAG

#2 Created at ... [Delete] [Delete and Lock User]

Array.form()是一种浅拷贝的方法,创建出的数组实例和源对象共享同一个内存地址。

如果对liAry[i].innerText进行赋值操作,可以看到对应的li.children[i].innerText也发生了改变。

所以在进行appendChild()操作时,系统认为插入的节点已经存在于当前的文档树,因此这个节点首先会从原先的位置删除,再插入到新的位置。

同样的,如果把上半部分的代码写成:

for(var i=0;i<liAry.length;i++)

li.appendChild(liAry[i]);

也不会保留原有元素。

creatElement()元素内存地址与原有元素不同,所以会被当成新节点直接插入。

我也在一边查资料一边学习,如果上面的结论有错误还请提出来。

肯频道

#3 Created at ... [Delete] [Delete and Lock User]

楼上说的是对的,因为直接forEach的写法,你打印每次的添加的效果会是

第一次Scheme,JavaScript,Python,Ruby,Haskell;

第二次Scheme,Python,Ruby,Haskell,JavaScript;

第三次Scheme,Ruby,Haskell,JavaScript,Python;

第四次Schem,Haskell,JavaScript,Python,Ruby;

第五次Haskell,JavaScript,Python,Ruby,Schem;

从尾部移动了你原排好序的元素,原元素的位置就被后面的元素顶上去了,我感觉还是使用第一种写法比较规范,容易理解。


  • 1

Reply