了解JavaScript方法的一种方法是滚动自己的版本。今天,让我们写Array.map
!
事实证明,Array.map
有两个参数:
- 在数组上循环时将应用的函数
- A
thisArg
,将是对对象的引用,该对象将是this
所提供函数中的上下文。
以我的经验,我并没有真正使用第二个参数,但是我们希望确保将其包括在内。
编写界面
由于我对扩展Array
原型不感兴趣,因此我将创建一个单独的map
函数。因此,我实际上将数组作为参数传递,这意味着我们将共有三个参数:
function map(arr, fn, thisArg) {
// Magic goes here
}
将功能应用于每个元素
在fn
我们提供必须施加到所述阵列的每个元素。让我们做到这一点。
function map(arr, fn, thisArg) {
const len = arr.length;
const result = new Array(len);
for (let i = 0; i < len; i++) {
if (i in arr) {
result[i] = fn(arr[i], i, arr);
}
}
return result;
}
重要的是,我们将三个参数传递给fn
:当前数组元素,当前数组元素的索引和原始输入数组。让我们来看一下实际情况:
const mapped = map([1, 2, 3], el => el * 2);
console.log(mapped);
// [2, 4, 6]
太好了,看起来基本操作正常!此示例不包括使用i
或arr
传递给我们的fn
,但您可以自己进行测试。
最后,thisArg
让我们不要忘记thisArg
!如果thisArg
提供,我们想确保我们bind
提供了的功能thisArg
。这是修改后的代码,以使其正常工作:
function map(arr, fn, thisArg) {
fn = thisArg === undefined ? fn : fn.bind(thisArg);
const len = arr.length;
const result = new Array(len);
for (let i = 0; i < len; i++) {
if (i in arr) {
result[i] = fn(arr[i], i, arr);
}
}
return result;
}
在这里,它正在起作用。(请注意,由于您无法重新绑定箭头函数的this
引用,因此我提供的函数不能是箭头函数。)
const obj = {
num: 10,
};
const mapped = map(
[1, 2, 3],
function (el) {
return el + this.num;
},
obj
);
console.log(mapped);
// [11, 12, 13]
而且我们可以看到this
是指obj
!
奖励:通过测试驱动的开发自己编写
我map
使用测试驱动开发(TDD)编写了此功能!我对所有需要通过的场景进行了测试Array.map
,然后一步一步地对代码进行重新设计以使它们通过。如果您尝试使用其他内置JS方法,请考虑使用此方法。
这是我用于该map
功能的测试:
describe("array", () => {
describe("map", () => {
it("maps a simple array", () => {
const arr = [1, 2, 3];
const fn = el => el * 10;
const answer = arr.map(fn);
expect(map(arr, fn)).toEqual(answer);
});
it("maps an empty array", () => {
const arr = [];
const fn = el => el * 10;
const answer = arr.map(fn);
expect(map(arr, fn)).toEqual(answer);
});
it("maps an array with holes", () => {
const arr = [1, 2, , , 3];
const fn = el => el * 10;
const answer = arr.map(fn);
expect(map(arr, fn)).toEqual(answer);
});
it("uses thisArg", () => {
const obj = {
0: "foo",
1: "bar",
2: "baz"
};
const arr = [1, 2, 3];
const fn = function(el, i) {
return this[i] + el;
};
const answer = arr.map(fn, obj);
expect(map(arr, fn, obj)).toEqual(answer);
});
it("uses the idx and arr parameters", () => {
const arr = [1, 2, 3];
const fn = (el, idx, arr) => JSON.stringify([el, idx, arr]);
const answer = arr.map(fn);
expect(map(arr, fn)).toEqual(answer);
});
});
希望您喜欢!让我知道您是否最终滚动了自己的其他内置方法版本。