在JavaScript中循环数组时的奇怪行为

时间:2018-03-17 09:27:25

标签: javascript arrays

我通过Eloquent Javascript阅读并面对其中一个练习,我发现了一个相当奇怪的行为。 (至少对我来说)

练习要求创建一个函数以反转数组。我以为我可以遍历数组,每次从原始数组中弹出一个项目并将其推送到最终将被返回的临时数组中。 但是当我使用for-of循环或典型的顺序循环遍历数组时,最后一项不会被传输。

有人可以告诉我究竟发生了什么吗?

const reverseArray = function(array) {
let rev = [];
for (let x = 0; x <= array.length; x++) {

    rev.push(array.pop());
    console.log(rev, array)
}
return rev;
};


console.log(reverseArray(["A", "B", "C"]));

输出:

["C"] ["A", "B"]
["C", "B"] ["A"]
["C", "B"]

6 个答案:

答案 0 :(得分:5)

pop()适用于array时,它会减少array的长度,因此当循环运行时,它会找到一个小于前一个数组长度的项目。因此,您可以做的只是在变量中指定array的长度,并在for循环的比较中使用它:

let rev = [];
const reverseArray = function(array) {
var length = array.length;
for (let x = 0; x < length; x++) {
  rev.push(array.pop());
}
return rev;
};


console.log(reverseArray(["A", "B", "C"]));

答案 1 :(得分:3)

pop()方法从数组中删除 pop'ed 项时,请使用while循环而不是for

let rev = [];
const reverseArray = function(array) {
    while (array.length > 0) {    // or just "(array.length)"
      rev.push(array.pop());
    }
    return rev;
}

console.log(reverseArray(["A", "B", "C"]));

使用closure,您可以为自己节省额外的全局变量

const reverseArray = function(array) {
  return (function(a_in,a_out) {
    while (a_in.length > 0) {    // or just "(a_in.length)"
      a_out.push(a_in.pop());
    }
    return a_out;
  })(array,[]);
}

console.log(reverseArray(["A", "B", "C"]));

或者如果允许Array.reverse()方法

const reverseArray = function(array) {
    return array.reverse();
}

console.log(reverseArray(["A", "B", "C"]));

答案 2 :(得分:1)

pop()方法删除数组的最后一个元素,并返回该元素。它会改变数组的长度。

const popArray = function(array) {
  for (let x = 0; x <= array.length; x++) {
      console.log("value of x :", x);
      console.log("array.length :", array.length);
      array.pop();
      console.log("array after", x + 1, "pop :", array);
  }
};

popArray(["A", "B", "C"]);

在上面的demo中我们可以看到每次pop()都发生在一个数组上。 array.length会减少,x的值会增加。因此,在某个时间点(第二次迭代后)x的值将是greater,然后是数组的长度。

使用 Array.from()方法:

let rev = [];
const reverseArray = function(array) {
  var destinationArray = Array.from(array);
  for (var i in Array.from(array)) {
    rev.push(array.pop());
    console.log(rev, array);
  }
};


reverseArray(["A", "B", "C"]);

答案 3 :(得分:0)

尝试使用while循环而不是for循环

const reverseArray = function(array){                                       
let rev = [];                                                             
while (array.length>0)                                                        
{                           
rev.push(array.pop());                                                       
}                                                  
return rev;                                                                  
};                                             
console.log(reverseArray(["A", "B", "C"]));

答案 4 :(得分:0)

我为你准备了两个版本。 reverse将反转数组而不修改原始数组。 reverseModify将执行相同操作,但清空原始数组。

选择最适合您的版本

const arr = [1, 2, 3, 4];

function reverse(array) {
  let result = [];
  for (let i = array.length - 1; i >= 0; i--) {
    result.push(array[i]);
  }
  
  return result;
}

function reverseModify(array) {
  let result = [];
  while (array.length) {
    result.push(array.pop());
  }
  
  return result;
}

console.log(reverse(arr), arr);
console.log(reverseModify(arr), arr);

答案 5 :(得分:0)

问题分为两个独立的操作。

  1. 迭代所有元素,通常采用长度并执行循环

  2. pop一个值和push that value. This is the mechanism to take the last项,并将其推送到新数组的末尾。

  3. 迭代部分只需要实际长度和倒计时(按pop)为零,然后退出循环。

    对于计数,你需要两个vvariables,一个用于计数器,一个用于数组的结尾或长度,这是一个静态值,取自给定的数组,后来发生变异。

    function reverseArray(array) {
        var rev = [];
      
        while (array.length) {
            rev.push(array.pop());
        }
        return rev;
    }
    
    console.log(reverseArray(["A", "B", "C"]));