循环删除子元素,却只删除了最后一个?

我用的zepto,一开始,采用如下代码:

let parent = $('.parent'),
  child = parent.find('.child');

for (let i = 0; i < 5; i++) {
  child.eq(-1).remove();
}

我的本意是希望删除最后五个子元素,但实际却只删除了最后一个。

我知道,可以通过如下代码删除:

let parent = $('.parent');

for (let i = 0; i < 5; i++) {
  parent.find('.child').eq(-1).remove();
}

这段代码。应该是每次循环,每次去查询dom,所以依次删了最后五个。

但我的疑问是,为何第一段代码不行?第一段里的 child 不会去查询dom结构吗?

阅读 5.3k
4 个回答

@SlaneYang 已经回答了问题的关键,注意 $.fn.remove()Array.prototype.pop() 是不一样的,后者是直接对数据进行操作,前者是从 DOM 树删除 DOM 元素(但元素仍然存在于内存,由 jQuery 对象/数组引用)

对于你这个问题,其实我建议先通过 .filter() 把需要的元素过滤出来,再一次性 remove()

const parent = $(".parent");
const children = parent.find(".child");
const firstIndexForRemoving = children.length - 5;
children.filter(i => i >= firstIndexForRemoving).remove();

顺便提一下

  • 我这个答案不是解决你的问题,只是锦上添花,喜欢请赞,但不太适合采纳
  • 对于不会再改变的变量,建议使用 const 声明而不是 let 声明
  • 尽量不要在声明变量的时候使用逗号运算符一次声明多个变量(压缩工具会自动处理成这种结果,但自己写代码不要这么写),尤其是对变量立即初始化的时候
  • child 在原程序中表示若干子项,应该使用复数 children 更为准确

假如parent下'.child'共有10个。
第一段代码中child = parent.find('.child');child变量是被缓存起来的,每次调用child.eq(-1).remove();child都是缓存的那10个元素,然后删除最后一个,重复了5次。

第二段代码中,则没有缓存的问题,每次for循环都会去查一遍parent下面现在有多少个.child元素,并且删除最后一个。

总结来说,就是第一段代码只查询了一次parent下的所有.child,而第二段代码,每次for循环都会去查询一遍。

望采纳

let parent = $('.parent');
// 这里的parent.find('.child')只执行了一次,然后用child变量暂存起来了。
// let child = parent.find('.child');
for (let i = 0; i < 5; i++) {
   // 而这里的child在循环里,所以执行了多次。
   var child = parent.find('.child');
   child.eq(-1).remove();
}
// 比如:
var sum = 0;
for (var i = 0; i < 5; i++) {
    console.log(sum++); // 输出0、1、2、3、4
}

for (var i = 0; i < 5; i++) {
    var sum2 = 0; // 每次循环sum2都是0
    console.log(sum2++); // 所以这里连续输出了5次0
}
// 这样是不是理解了些。(望采纳)

第一个是获取到子元素形成了一个伪数组,记住是伪数组,而且在循环之前里面的元素就固定了,这样你循环删除其最后一个元素其实指向的就是最后一个,而放在里面查找子元素形成新的伪数组进行删除,每次就能删除到最后一个。
关于伪数组和数组这是有区别的,不能混为一谈,操作数组的结果和操作伪数组可不一定会得到一样结果。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题