【问题标题】:Javascript splice for array of DOM elementsDOM元素数组的Javascript拼接
【发布时间】:2015-02-22 13:58:05
【问题描述】:
var myArray = [];
myArray = document.querySelectorAll('.selected');

当我调用 myArray.splice - 它是未定义的。我怎样才能避免这种情况?我需要从该数组中删除一些 DOM 元素。

【问题讨论】:

  • 你能给我们看看HTML代码,选择了类吗?
  • myArray 是 Nodelist 而不是普通数组
  • 我希望你不要想象从节点列表中删除元素会从文档中删除它们。为什么要从数组中移除元素?
  • @torazaburo,我没有想象这个。我只想从 myArray 中删除一些元素。

标签: javascript arrays


【解决方案1】:

document.querySelectorAll 返回 NodeList,而不是数组。

因此 NodeList 上默认没有 Splice 方法。

但是,您可以为 A 节点列表制作类似方法的原型。

这是一个有效的JSFiddle,它直接从 DOM 中删除像 splice 这样的元素,你可以随意修改它。

var myArray = [];
myArray = document.querySelectorAll('.selected');

//This is a primitive analogue of splice without adding new elements, it will not remove element from NodeList, however will remove it directly from dome, then it will return the resulting array (As Array), because NodeList is unmodifiable;
NodeList.prototype.splice = function(pos, numToRemove){
    var initRemCount = remCount = numToRemove ? numToRemove : 1;
    var removed = [];
    for(var i = 0; i < this.length; i++){
        if(!remCount)
            break;
        var elm = this[i];
        if(i >= pos){
            //elm.parentElement.removeChild(elm); //I commented this out, 'cause you say you dont want to delete members from DOM, uncomment this to do so
            remCount--;
        }
    }
    return [].slice.call(this, pos, pos + initRemCount); 
}

var resultArray = myArray.splice(2, 2);

//This is the Araay already not a NodeList
console.log(resultArray);

【讨论】:

  • 当您可以简单地将节点列表转换为数组时,几乎没有必要使用新例程(尤其是可枚举的例程)污染NodeList 原型。此外,OP 表示他不希望从 DOM 中删除元素。最后,此实现与Array.splice API 不同,不处理用于添加新元素的附加参数。
  • 好的,请注意。抱歉,我没有提到对象必须留在 DOM 中。但是,您澄清了评论的第一部分。
  • 我的意思是这个问题几乎总是通过将节点列表转换为数组来处理;那么您可以直接使用现有的Array#splice。您的解决方案可以正常工作,但我怀疑您是否想将所有数组方法放在 NodeList 上,这将是您的方向。
  • @torazaburo 我同意。但是MDN almost suggests this someway。你建议我编辑我的解决方案吗?
  • 我会说 MDN “呈现”它,而不是“建议”它,它警告说“扩展 DOM 是危险的”,但它仍然是处理事情的一种方式,所以不,我认为您不必对其进行编辑。
【解决方案2】:

问题在于 querySelectorAll(..) 返回一个节点列表 (NodeList)——不是标准的 JS 数组。

您可能想要以下内容:

Array.prototype.slice.call(document.querySelectorAll('.selected'),  <begin>, <end>);

更新

我错过了您要删除的部分,谢谢@torazaburo。幸运的是,您可以直接在 NodeList 上应用过滤器,而不是通过数组转换。如下所示:

var arrayOfNodes = [].filter.call(document.querySelectorAll(".selected"), function(curNodeItem) {
     return shouldCurrentNodeBeRetained(curNodeItem)? true : false;
    //expanded for clarity.    
});

【讨论】:

  • 他试图调用splice 来删除元素,而不是slice 来选择它们。
【解决方案3】:

querySelectorAll 是一个NodeList array-like collection,但它不是一个数组,因为它不是从Array.prototype 继承的。要将其转换为真实数组,您可以这样使用slice

var myArray = [].slice.call(document.querySelectorAll('.selected'));

可以像这样使用slice,因为Array.prototype.slice 是有意的通用方法,这意味着它的内部实现不会检查this 值是否实际上是Array 实例。所以slice 可以与任何类似数组的对象一起使用,具有数字索引和length 属性。

【讨论】:

    猜你喜欢
    • 2010-10-04
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    相关资源
    最近更新 更多