.forEach索引超出数组的长度

时间:2018-02-01 16:59:04

标签: javascript arrays

我正在使用CodeFights,我仍然在学习javascript。我正在做他们的一个基本挑战,我遇到了麻烦。

我不想要解决方案,而是解释我的代码发生了什么。代码的目的是简单地返回数组中任意两个相邻元素的最高乘积。我认为代码运行的最后一次nextNum变量被设置为NaN,因为它是一个不存在的索引。我想我很困惑,为什么我的代码仍然将最高产品更改为18当NaN!= 1据我知道而且我不知道18甚至会来自哪里,除非它再次开始循环。任何帮助非常感谢。

这是:

function adjacentElementsProduct(inputArray) {
    let highestProduct;
    inputArray.forEach(function(loopNum) {
        let nextNum = inputArray.indexOf(loopNum) + 1;
        let newProduct = inputArray[nextNum] * loopNum;
        if (nextNum === 1) {
            highestProduct = newProduct;
        } else if (newProduct > highestProduct) {
            highestProduct = newProduct;
        }
        console.log(highestProduct);
    })
    return highestProduct;
}
let testArr = [3, 6, -2, -5, 7, 3]
console.log(adjacentElementsProduct(testArr));

3 个答案:

答案 0 :(得分:3)

由于这条线,它又回到了18:

let nextNum = inputArray.indexOf(loopNum) + 1;

在最后一个循环中,loopNum3。数组中有两个3,一个在开头,另一个在结尾。当你到达终点时,indexOf会在开头找到一个,返回索引0,然后将其添加到nextNum,并将其分配给1。这意味着这将开始:

if (nextNum === 1) {
    highestProduct = newProduct;

...并将highestProduct设置为18,即使它在前一次传球中为21。

作为Patrick Roberts pointed out,您不需要发现索引,因为forEach回调将其作为第二个参数接收。正如你所指出的那样,你意识到你需要在数组中提前停止一个。

所以这两个小改动:

function adjacentElementsProduct(inputArray) {
    let highestProduct;
    inputArray.forEach(function(loopNum, index) {            // ***
        let nextNum = index + 1;                             // ***
        if (nextNum < inputArray.length) {                   // ***
            let newProduct = inputArray[nextNum] * loopNum;
            if (nextNum === 1) {
                highestProduct = newProduct;
            } else if (newProduct > highestProduct) {
                highestProduct = newProduct;
            }
            console.log(highestProduct);
        }
    })
    return highestProduct;
}
let testArr = [3, 6, -2, -5, 7, 3]
console.log(adjacentElementsProduct(testArr));

到目前为止,了解这类内容的最佳方法是使用IDE或浏览器中内置的调试器逐步执行它,逐个语句,查看变量的值等等你走了。

答案 1 :(得分:0)

你的代码正在经历循环,当它到达数组的最后一个元素时,它会拉出产品的下一个元素并返回索引1.这是解释。

nextNum: 1 newProduct: 18 highestProduct: undefined
inputArray[1]: 6 loopNum: 3
nextNum: 2 newProduct: -12 highestProduct: 18
inputArray[2]: -2 loopNum: 6
nextNum: 3 newProduct: 10 highestProduct: 18
inputArray[3]: -5 loopNum: -2
nextNum: 4 newProduct: -35 highestProduct: 18
inputArray[4]: 7 loopNum: -5
nextNum: 5 newProduct: 21 highestProduct: 18
inputArray[5]: 3 loopNum: 7
nextNum: 1 newProduct: 18 highestProduct: 21
inputArray[1]: 6 loopNum: 3
18

答案 2 :(得分:0)

For I came up with something very close to @T.J.Crowder 's answer, I stopped posting mine though taking the chance to go even one step further.

Since the main issue had to be solved with using a better comparison and index as 2nd callback parameter, I want to point to a more suitable array iterator method than forEach for the given case is ... reduce. With this method the logic within a customized callback function can be achieved with better readable and less code.

The following provided example code should not be seen as an answer to the OP but more as an example of what can be done with refactoring and using better suitable tools ...

function collectMaximumAdjacentElementsProduct (maxProduct, number, idx, numberList) {
    var
        nextNumber = numberList[idx + 1];

    if (typeof nextNumber !== 'undefined') {
        maxProduct = Math.max(maxProduct, (number * nextNumber));
    }
    return maxProduct;
}

var arr = [3, 6, -2, -5, 7, 3];
var num = arr.reduce(collectMaximumAdjacentElementsProduct, Number.NEGATIVE_INFINITY)

console.log('collectMaximumAdjacentElementsProduct', arr, ':', num);
.as-console-wrapper { max-height: 100%!important; top: 0; }