【问题标题】:JavaScript Jest Testing; Using Callback Function to Modify Elements in ArrayJavaScript 笑话测试;使用回调函数修改数组中的元素
【发布时间】:2018-06-28 20:09:11
【问题描述】:

我正在使用 Jest 测试库来测试一个调用回调的函数,该回调采用两个参数,element[i]i

这是我要测试的功能:

const each = (elements, cb) => {
  for (let i = 0; i < elements.length; i++) {
    cb(elements[i], i);
  }
};

我知道数组只会有数字,所以在测试函数中我试图让回调简单地将索引添加到数组中的每个数字;例如,它应该将[1, 2, 3, 4] 的数组更改为[1, 3, 5, 7]

这是我尝试做的:

const arrayFunctions = require('./arrays');

describe('Arrays', () => {
    it('each', () => {
        const callBack = (elem, indx) => {
            elem += indx;  
        }
        const arr = [1, 2, 3, 4];
        arrayFunctions.each(arr, callBack);
        expect(arr).toEqual([1, 3, 5, 7]);
    })
});

这是我得到的错误:

 Received:
      [1, 2, 3, 4]

    Difference:

    - Expected
    + Received

      Array [
        1,
    +   2,
        3,
    -   5,
    -   7,
    +   4,
      ]

      15 |         const arr = [1, 2, 3, 4];
      16 |         arrayFunctions.each(arr, callBack);
    > 17 |         expect(arr).toEqual([1, 3, 5, 7]);
         |                     ^
      18 |     })
      19 | });
      20 |

      at Object.it (advanced-javascript/arrays.spec.js:17:21)

为什么它没有按预期修改数组?再举一个更简单的例子,为什么会这样:

const arr = [1, 2, 3, 4];
for (let i = 0; i < arr.length; i++) {
  arr[i] += i;
}
console.log(arr) // [1, 3, 5, 7];

虽然这不是?

const arr = [1, 2, 3, 4];
each(arr, callBack);
console.log(arr); // [1, 2, 3, 4];

【问题讨论】:

  • 数字是不可变的。分配参数不会影响数组。
  • 听起来好像您正试图让each 更像mapmap 是关于转换值。 each 是关于创建副作用的。你在找哪个? (我假设你明白这些已经内置在 `Array.prototype 中。)
  • @ScottSauyet 我是 Lambda 学校的学生,目前正在使用 JavaScript 进行 Jest 测试;我知道数组的内置方法,但是为了这个练习,是的,我试图让each 函数更像map。有什么建议吗?
  • 嗯,我不知道你的ˋeachˋ 是否正确,但我知道测试没有问正确的问题。其他 cmets 和答案应该会引导您朝着正确的方向前进。

标签: javascript arrays callback jestjs


【解决方案1】:

不同之处在于索引分配的微妙之处。它看起来像两个运算符([n]+=),但实际上是一个:[n]+=。最后使用+= (add and assign) 和[n] += (add and assign to value at index) 是不一样的,所以你可以在索引和赋值字符之间放空格(奇怪的是,即使是括号,但这只是令人困惑),但你不能将它分成单独的语句行,这实际上就是你正在做的事情(见下文)。

让我们创建自己的数组,看看我们将如何实现[n](我们称之为get(n))和[n]=value(我们称之为函数set(n, value)。为了便于阅读,我将使用新的类语法。

class FakeArray {
  get(index) {
    var valueAtIndex = // somehow get that value
    return valueAtIndex
  }

  set(index, value) {
    //somehow set that value
  }
}

现在考虑是否可以使用get 实现set。这行得通吗?:

  set(index, value) {
    this.get(index) = value
  }

不会的。您会收到错误消息:ReferenceError: Left side of assignment is not a reference.(您可以更改引用的值,但不能更改值的值)。但是,如果可以,您将不需要 set 函数。您可以将 get 函数与 =(以及 +=-= 等)结合使用。但是你不能把它们分开,所以它们是完全不同的函数/运算符。 [n][n]= 也是如此。它们的工作方式完全不同,它们不是两者的组合。


此外,当您将值传递给函数时,您实际上是在将它们分配给一个新变量:

var a = 1;

function foo (b) {
  b = b + 1
  console.log(b)
};

foo(a)
console.log(a)

主要等同于:

var a = 1;

var b = a
b = b + 1
console.log(b)

console.log(a)

这称为按值传递,它是javascript中传递值的唯一方法。有关详细信息,请参阅此答案:What's the difference between passing by reference vs. passing by value?

【讨论】:

  • 我了解代码示例,但您能否详细说明您对+= 两个运算符的解释?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-09
  • 2015-10-17
  • 2020-12-16
相关资源
最近更新 更多