Javascript 为什么数组在删除后仍然具有非零长度?

Javascript 为什么数组在删除后仍然具有非零长度?,javascript,arrays,Javascript,Arrays,我有以下代码输出数组的长度,删除它,然后输出新的长度: console.log($scope.adviceList.activeAdvices.length); // *1* $scope.adviceList.activeAdvices.splice(id,1); // *id is a parameter* console.log($scope.adviceList.activeAdvices.length); // *0* console.log($scope.adviceList.ac

我有以下代码输出数组的长度,删除它,然后输出新的长度:

console.log($scope.adviceList.activeAdvices.length); // *1*
$scope.adviceList.activeAdvices.splice(id,1); // *id is a parameter*
console.log($scope.adviceList.activeAdvices.length); // *0*

console.log($scope.adviceList.activeAdvices.length); // *1*
delete $scope.adviceList.activeAdvices[id];
console.log($scope.adviceList.activeAdvices.length); // *0*
console.log($scope.adviceList.activeAdvices); // *[]*

删除后,数组将正确显示为空。然而,它的长度仍然是1。

这是因为数组元素上的delete将其设置为undefined,所以长度不会改变。改用
拼接
功能:

a = [1,2,3,4];
a.splice(2,1);
console.log(a.length);
delete
是一个“低级”操作符。它直接作用于对象,不“知道”数组。使用
delete
不会触发例程重新计算数组长度


这里的其他答案声称属性的值设置为
unddefined
,这是不正确的。一个简单的测试表明:

var a = [1]; 
delete a[0]; 
console.dir(a);
并与实际将值设置为未定义时发生的情况进行比较:

var a = [1]; 
a[0] = undefined; 
console.dir(a);
为了获得更可靠的证据,让我们看一下:

当使用属性名p和布尔标志Throw调用O的[[Delete]]内部方法时,将执行以下步骤:

  • 让desc作为调用属性名为P的O的[[GetOwnProperty]]内部方法的结果
  • 如果desc未定义,则返回true
  • 如果desc.[Configurable]]为true,则
    A.从O中删除名为P的自有属性。
    B返回真值
  • 否则,如果抛出,则抛出一个TypeError异常
  • 返回false 在任何地方都不能说该属性的值设置为
    未定义


    不同浏览器的控制台可能会显示阵列的不同表示形式。在这个特定的示例中,您可以讨论它应该是
    []
    还是
    [undefined]

    • []
      (Chrome)似乎有意义,因为数组实际上没有任何元素,没有带有数字名称的属性。但是,当您访问
      .length
      属性时,会得到一个
      1
      ,这可能会让人困惑。
      不久前,Chrome用于表示长度为5但没有元素的数组。我认为这实际上是一个很好的解决方案

    • [undefined]
      (Firefox)之所以有意义,是因为数组的长度为1,访问
      arr[0]
      实际上返回
      undefined
      (但
      arr[10]
      也是如此)。但是,
      arr.hasOwnProperty(0)
      将是
      false
      ,如果数组确实包含
      undefined
      ,则,仅凭这种表示法,如何将其与长度为1的空数组区分开来(回答:您不能)

    底线是:不要太信任控制台。日志。如果您想要精确的表示,请使用
    console.dir

    如果您想要“删除”数组中的项目,您可以

    var a = ["a","b"];
    console.log(a);  //a,b
    console.log(a.length);//2
    a.length = 1;//"delete" all greater than length 1 of items;
    console.log(a);//a
    console.log(a.length);//1
    


    就我而言,我在删除后重新定义了长度:

    var cars = ["BMW", "Volvo", "Saab", "Ford"];
    delete cars[1];
    
    /// 1st option ///
    for (var i = 0; i < cars.length; i++){
      if(i in cars)
        document.write(cars[i] + " ");
    }
    /// return: BMW Saab Ford
    
    /// 2nd option ///
    cars.length--;
    var realLength = cars.length;
    
    var cars=[“宝马”、“沃尔沃”、“萨博”、“福特”];
    删除汽车[1];
    ///第一选项///
    对于(变量i=0;i
    我创建了一个新数组,并将
    编辑的元素推到数组上,以获得正确的长度。例如,我对表格标题有以下内容:

     var finalTableHeaderArray = [];
    
     tableHeaderArray.forEach(function (element, index, array) {
        if (removeDisplayItems.indexOf(index) === -1)
            finalTableHeaderArray.push(element);
     }, self);
    

    不完全是您的问题,但它可以帮助其他人。

    这些变量在哪里声明?请参阅
    delete
    中可能重复的第一个答案是“较低”级别的运算符。它直接作用于对象,不“知道”数组。使用
    delete
    不会触发例程重新计算数组长度。“delete实际上不会删除该项,而是将其设置为未定义”这是不正确的。该属性将被删除。尝试
    var a=[1];删除[0];目录(a)
    为什么你要投我的反对票当我写这篇文章时,
    删除后数组对象的解释是
    [undefined]
    @Antti:你怎么会认为我投了你的反对票?我没有。正如我已经评论过的,我被你的控制台输出(
    [undefined]
    )弄糊涂了,没有仔细阅读你的答案就下结论,这就是我评论的原因。然而,我没有投反对票。有一件事让我更加困惑,那就是MDN说,对于forEach,未定义的和没有属性的行为应该是相同的,但即使在FirefoxMine上,它们的行为也不相同。Chrome说,未定义。@johnny:访问不存在的属性将返回
    未定义的
    。这与将属性设置为
    undefined
    不同(正如我在回答中所演示的那样)。简单有效
     var a = ["a","b"];
        console.log(a);  //a,b
        console.log(a.length);//2
        a.splice(1,1);//"delete" from index 1(include,first parameter),delete number is 1(second parameter)
        console.log(a);//a
        console.log(a.length);//1
    
    var cars = ["BMW", "Volvo", "Saab", "Ford"];
    delete cars[1];
    
    /// 1st option ///
    for (var i = 0; i < cars.length; i++){
      if(i in cars)
        document.write(cars[i] + " ");
    }
    /// return: BMW Saab Ford
    
    /// 2nd option ///
    cars.length--;
    var realLength = cars.length;
    
     var finalTableHeaderArray = [];
    
     tableHeaderArray.forEach(function (element, index, array) {
        if (removeDisplayItems.indexOf(index) === -1)
            finalTableHeaderArray.push(element);
     }, self);