对于JavaScript多维数组的深层副本,深入一层似乎就足够了。这可靠吗?

对于JavaScript多维数组的深层副本,深入一层似乎就足够了。这可靠吗?,javascript,arrays,multidimensional-array,Javascript,Arrays,Multidimensional Array,注意:我只是一个新手,所以这个问题的核心可能有一个明显的错误或误解 本质上,我需要在JavaScript中将多维数组“按值”深度复制到未知的深度。我认为这需要一些复杂的递归,但在JavaScript中,似乎只需要复制一个级别的深度,就可以按值复制整个数组 作为一个例子,这里是我的测试代码,使用一个故意卷积的数组 function test() { var arr = [ ['ok1'],[],[ [],[],[ [], [ [ ['ok2'], [] ] ] ] ] ]; var clo

注意:我只是一个新手,所以这个问题的核心可能有一个明显的错误或误解

本质上,我需要在JavaScript中将多维数组“按值”深度复制到未知的深度。我认为这需要一些复杂的递归,但在JavaScript中,似乎只需要复制一个级别的深度,就可以按值复制整个数组

作为一个例子,这里是我的测试代码,使用一个故意卷积的数组

function test() {
  var arr = [ ['ok1'],[],[ [],[],[ [], [ [ ['ok2'], [] ] ] ] ] ];
  var cloned = cloneArray(arr);
  arr = '';   // Delete the original
  alert ( cloned );
}


function cloneArray(arr) {  
  // Deep copy arrays. Going one level deep seems to be enough.
  var clone = [];
  for (i=0; i<arr.length; i++) {
    clone.push( arr[i].slice(0) )
  }
  return clone;
}
功能测试(){
var arr=[['ok1']、[]、[[]、[]、[[]、[[]、[[]、[[[]、[[[ok2']、[]];
var=cloneArray(arr);
arr='';//删除原始文件
警报(克隆);
}
函数cloneArray(arr){
//深度复制阵列。深入一层似乎就足够了。
var克隆=[];

对于(i=0;i您的代码不起作用:

  • 如果数组包含其他变量,如数字或字符串(不仅仅是数组),它将失败,因为它将调用
    arr[i].slice()
    ,但由于
    arr[i]
    是一个数字,因此它没有任何
    .slice
    属性,这将引发错误
  • 在任何情况下,您的函数都将保留对数组中对象和其他内容的所有引用,因此您实际上不会获得数组的副本
例如:

var a = [1,2, [11,13], ['ok']];
var b = cloneArray(a);

> TypeError: undefined is not a function // because numbers have no .slice method
解决方案: 要复制数组,您需要对其进行深度复制。由于创建深度复制需要一个使用递归的函数对主数组中的任何对象或数组进行深度复制,最简单的方法是使用jQuery及其
.extend
方法,该方法执行数组的深度复制,请参阅以获取更多信息

var a =[[1], [2], [3]];
var b = $.extend(true, [], a);

b[0][0] = 99;
a[0][0] // still 1

您的测试在是否创建了真实副本方面存在缺陷,这使得您的结论不正确,即您正在获取嵌套数组中所有数据的完整副本。您只执行两级副本,而不是N级副本

Javascript是一种垃圾收集语言,因此您实际上不会删除变量或对象,即使您尝试删除,如果代码中的其他地方引用了相同的变量,也不会影响该变量。若要查看您是否真正拥有完全独立的副本,请尝试将对象嵌套两层,然后在中更改对象的属性原始数组。您将发现克隆数组中的相同对象发生了更改,因为您没有进行深度克隆。两个数组都引用了完全相同的对象

给你

函数cloneArray(arr){ //深度复制阵列。深入一层似乎就足够了。 var克隆=[]; 对于(i=0;i


仅供参考,您的
cloneArray()
函数假定数组的所有第一级成员本身都是数组,因此如果它包含任何其他类型的值,则不起作用。

数组.prototype.slice不适合克隆数组

这应该对你有好处

function deepClone(arr) {
  var len = arr.length;
  var newArr = new Array(len);
  for (var i=0; i<len; i++) {
    if (Array.isArray(arr[i])) {
      newArr[i] = deepClone(arr[i]);
    }
    else {
      newArr[i] = arr[i];
    }
  }
  return newArr;
}

下面是我“克隆”多维数组的递归方法。它一直运行到最深层:

if ( !Array.clone )
{
        Array.prototype.clone = function()
        {
                var _arr = ( arguments[0] == null ) ? [] : arguments[0] ; 
                for( var _p = 0 ; _p < this.length ; _p++ )
                {
                         if ( this[_p] instanceof Array )
                         {
                                 var _sub = [] ;
                                 this[_p].clone( _sub ) ;
                                 _arr.push( _sub.slice() );
                         }
                         else _arr.push( this[_p] );
                }

                return _arr ;
        }
}

变量a和变量b是两个不同的对象:如果从变量b中删除一个元素,那么变量a不会受到影响。

这并不是问题的答案。只是jQuery根本不是问题的一部分。解决方案通常只需要在OP提到jQuery或标记了jQuery时才需要jQuery。现在,这是一个plain javascript问题。还有,为什么你的第一个要点提到
.split()
,而这与问题或答案无关?看起来你只是在做数组的深度复制,而不是对象。是的,这符合问题的要求。提问者没有提到复制(非数组)的要求对象。事实上,正如您所说,我似乎遇到了垃圾收集行为。我将测试更改如下:,对原始数组的更改确实影响了我所谓的“克隆”数组。事实上,我可以首先(和第二)依赖这些阵列的顺序成员本身就是阵列,没有一个成员是对象。我想采用DIY方法,即使这意味着重新发明轮子(只是为了学习经验),因此我将尝试使用自己的系统可靠地克隆阵列。感谢您的帮助。在stackoverflow上,您不应编辑问题以提供最终答案。这是最佳答案名称。stackoverflow希望问题显示为您最初提出的样子(加上任何澄清性编辑)这就是人们稍后回来时看到的上下文。好的,我将把问题编辑回原始状态。
if(!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}
if ( !Array.clone )
{
        Array.prototype.clone = function()
        {
                var _arr = ( arguments[0] == null ) ? [] : arguments[0] ; 
                for( var _p = 0 ; _p < this.length ; _p++ )
                {
                         if ( this[_p] instanceof Array )
                         {
                                 var _sub = [] ;
                                 this[_p].clone( _sub ) ;
                                 _arr.push( _sub.slice() );
                         }
                         else _arr.push( this[_p] );
                }

                return _arr ;
        }
}
var _a = [ "a", "b", [ "c", "d", [ "e", "f" ] ] ];
var _b = _a.clone();
console.log( _b );