并在这些版本的基础上进行构建
发布时间:2020-01-04 16:16

要在给定数组上应用方法,只须要经过[].方法名就能够,这一个情势都定义在Array.prototype对象上。在那地,我们先不使用这个相,反,我们将从轻松的不二等秘书籍早先定义自身的版本,并在此些本子的功底上实行营造。

从没有过比把东西拆开再重新建立起来更加好的读书格局了。注意,当大家的达成和睦的艺术时,不要覆盖现成的艺术,因为有的库须要它们,况兼那样也造福相比我们自个儿的方式与原来方法的异样。

故此不要这么命名我们自定义的主意:

Array.prototype.map = function map() { // implementation};

也就这样命名:

function map(array) { // implementation}

大家也得以通过应用class关键字并扩展Array布局函数来兑现大家的格局,如下所示:

class OwnArray extends Array { public constructor(...args) { super(...args); } public map() { // implementation return this; }}

独一的界别是,大家不采纳数组参数,而是使用this关键字。不过,作者认为 class 情势带来不要求的混乱,所以大家选用第大器晚成种艺术。有了这些,我们先从完成最轻易易行的艺术forEach开端!

集合类.forEach

Array.prototype.forEach方法对数组的各种成分试行一遍提供的函数,何况不会纠正原数组。

[1, 2, 3, 4, 5].forEach(value = console.log(value));

实现

function forEach(array, callback) { const { length } = array; for (let index = 0; index  length; index += 1) { const value = array[index]; callback(value, index, array) }}

大家遍历数组并为每一个成分实施回调。这里须求介怀的一点是,该措施未有回去什么,所以默许重返undefined。

方法涟

应用数组方法的功利是能够将操作链接在一起。思量以下代码:

function getTodosWithCategory(todos, category) { return todos .filter(todo = todo.category === category) .map(todo = normalizeTodo(todo));}

这种方式,大家就无需将map的执行结果保存到变量中,代码会更简洁。

噩运的是,forEach未有回到原数组,那意味着我们不能够做上面包车型地铁业务

// 无法工作function getTodosWithCategory(todos, category) { return todos .filter(todo = todo.category === category) .forEach((value) = console.log(value)) .map(todo = normalizeTodo(todo));}

援救函数

继之达成三个粗略的函数,它能越来越好地表达各种方法的效率:接收什么作为输入,重临什么,以至它是否对数组进行了退换。

function logOperation(operationName, array, callback) { const input = [...array]; const result = callback(array); console.log({ operation: operationName, arrayBefore: input, arrayAfter: array, mutates: mutatesArray(input, array), // shallow check result, });}

个中 mutatesArray 方法用来判别是还是不是变动了原数组,纵然有改过刚回来true,不然再次回到false。当然大伙有好的主见能够在评价建议呦。

function mutatesArray(firstArray, secondArray) { if (firstArray.length !== secondArray.length) { return true; } for (let index = 0; index  firstArray.length; index += 1) { if (firstArray[index] !== secondArray[index]) { return true; } } return false;}

然后采纳logOperation来测验我们前边自身完成的forEach方法。

logOperation('forEach', [1, 2, 3, 4, 5], array = forEach(array, value = console.log(value)));

打字与印刷结果:

{ operation: 'forEach', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: undefined}

.map

map方法会给原数组中的每一种成分都按顺序调用叁回callback函数。callback每一次施行后的重回值组合起来变成一个新数组。

实现

function map(array, callback) { const result = []; const { length } = array; for (let index = 0; index  length; index +=1) { const value = array[index]; result[index] = callback(value, index, array); } return result;}

提须要艺术的回调函数采纳旧值作为参数,并再次回到一个新值,然后将其保存在新数组中的相仿索引下,这里用变量result表示。

那边供给留意的是,大家重返了一个新的数组,不改革旧的。

测试

logOperation('map', [1, 2, 3, 4, 5], array = map(array, value = value + 5));

打字与印刷结果:

{ operation: 'map', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: [ 6, 7, 8, 9, 10 ] }

.filter

Array.prototype.filter过滤回调重临为false的值,每一个值都保存在三个新的数组中,然后重回。

[1, 2, 3, 4, 5].filter(number = number = 3);// - [3, 4, 5]

实现

function push(array, ...values) { const { length: arrayLength } = array; const { length: valuesLength } = values; for (let index = 0; index  valuesLength; index += 1) { array[arrayLength + index] = values[index]; } return array.length;}--------------------------------------------------function filter(array, callback) { const result = []; const { length } = array; for (let index = 0; index  length; index += 1) { const value = array[index]; if (callback(value, index, array)) { push(result, value); } } return result;}

赢得每种值并检讨所提供的回调函数是还是不是重回true或false,然后将该值增加到新创设的数组中,恐怕适度地抛弃它。

留意,这里对result数组使用push方法,并非将值保存在传入数组中放置的相近索引中。那样,result就不会因为抛弃的值而有空槽。

测试

logOperation('filter', [1, 2, 3, 4, 5], array = filter(array, value = value = 2));

运行:

{ operation: 'filter', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: [ 2, 3, 4, 5 ] }

.reduce

reduce(卡塔尔(قطر‎方法选取三个函数作为累加器,数组中的每一种值初阶减小,最终总结为一个值。reduce(State of Qatar方法接收三个参数:早先值,当前成分值,当前目录,调用 reduce(卡塔尔 的数组

适逢其会地说,如何总计该值是亟需在回调中钦定的。来看呓使用reduce的八个简易的例证:对生龙活虎组数字求和:

 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].reduce((sum, number) = { return sum + number; }, 0) // - 55

留意这里的回调选取四个参数:sum和number。第一个参数总是前一个迭代重临的结果,第四个参数在遍历中的当前数组成分。

此间,当我们对数组举行迭代时,sum包罗到循环当前目录的富有数字的和因为老是迭代大家都将数组的近来值增加到sum中。

实现

function reduce(array, callback, initValue) { const { length } = array; let acc = initValue; let startAtIndex = 0; if (initValue === undefined) { acc = array[0]; startAtIndex = 0; } for (let index = startAtIndex; index  length; index += 1) { const value = array[index]; acc = callback(acc, value, index, array) } return acc;}

笔者们创设了三个变量acc和startAtIndex,并用它们的默许值早先化它们,分别是参数initValue和0。

下一场,检查initValue是还是不是是undefined。如若是,则必得将数组的率先个值设置为初值,为了不另行总计早先成分,将startAtIndex设置为1。

每便迭代,reduce方法都将回调的结果保存在累计器(accState of Qatar中,然后在下二个迭代中接收。对于第一遍迭代,acc被安装为initValue或array[0]。

测试

logOperation('reduce', [1, 2, 3, 4, 5], array = reduce(array, (sum, number) = sum + number, 0));

运行:

{ operation: 'reduce', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: 15 }

检索类

有啥样操作比寻觅一定值更分布?这里有部分方法可以补助大家。

.findIndex

findIndex协助大家找到数组中给定值的目录。

[1, 2, 3, 4, 5, 6, 7].findIndex(value = value === 5); // 4

findIndex方法对数组中的各样数组索引0..length-1施行贰次callback函数,直到找到一个callback函数再次回到真实值的值。如若找到这么的成分,findIndex会马上回去该因素的目录。假设回调从不重返真值,或许数组的length为0,则findIndex重回-1。

实现

function findIndex(array, callback) { const { length } = array; for (let index = 0; index  length; index += 1) { const value = array[index]; if (callback(value, index, array)) { return index; } } return -1;}

测试

logOperation('findIndex', [1, 2, 3, 4, 5], array = findIndex(array, number = number === 3));

运行:

{ operation: 'findIndex', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: 2}

.find

find与findIndex的头一无二不一样在于,它回到的是实际值,并不是索引。实际工作中,我们能够选取已经完成的findIndex。

[1, 2, 3, 4, 5, 6, 7].find(value = value === 5); // 5

实现

function find(array, callback) { const index = findIndex(array, callback); if (index === -1) { return undefined; } return array[index];}

测试

logOperation('find', [1, 2, 3, 4, 5], array = find(array, number = number === 3));

运行

{ operation: 'find', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: 3}

.indexOf

indexOf是获得给定值索引的另生机勃勃种方式。可是,那叁次,大家将实际值作为参数实际不是函数字传送递。相近,为了简化达成,可以行使前边达成的findIndex

[3, 2, 3].indexOf(3); // - 0

实现

function indexOf(array, searchedValue) { return findIndex(array, value = value === searchedValue)}

测试

logOperation('indexOf', [1, 2, 3, 4, 5], array = indexOf(array, 3));

施行结果

{ operation: 'indexOf', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: 2}

.lastIndexOf

lastIndexOf的办事措施与indexOf相符,lastIndexOf(State of Qatar方法再次回到钦命成分在数组中的最终叁个的目录,假如不设有则赶回-1。

[3, 2, 3].lastIndexOf(3); // - 2

实现

function lastIndexOf(array, searchedValue) { for (let index = array.length - 1; index  -1; index -= 1 ){ const value = array[index]; if (value === searchedValue) { return index; } } return -1;}

代码基本与findIndex近似,可是从未执行回调,而是比较value和searchedValue。假若相比结实为true,则赶回索引,就算找不到值,再次来到-1。

测试

logOperation('lastIndexOf', [1, 2, 3, 4, 5, 3], array = lastIndexOf(array, 3));

试行结果

{ operation: 'lastIndexOf', arrayBefore: [ 1, 2, 3, 4, 5, 3 ], arrayAfter: [ 1, 2, 3, 4, 5, 3 ], mutates: false, result: 5 }

.every

every(卡塔尔国方法测量检验一个数组内的富有因素是不是都能透过某个钦点函数的测量试验,它回到一个布尔值。

[1, 2, 3].every(value = Number.isInteger(value)); // - true

大家可以将every方法看作叁个等价于逻辑与的数组。

实现

function every(array, callback){ const { length } = array; for (let index = 0; index  length; index += 1) { const value = array[index]; if (!callback(value, index, array)) { return false; } } return true;}

作者们为各样值实施回调。假若在其他时候回来false,则脱离循环,整个艺术重回false。若是循环终止而尚未进来到if语句里面(表明条件都创造卡塔尔,则方法重返true。

测试

logOperation('every', [1, 2, 3, 4, 5], array = every(array, number = Number.isInteger(number)));

实行结果

{ operation: 'every', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: true }

.some

some方法与every正好反而,即如若个中二个为true就能够重返true。与every方法类似,大家能够将some方法看作三个等价于逻辑或数组。

[1, 2, 3, 4, 5].some(number = number === 5); // - true

实现

function some(array, callback) { const { length } = array; for (let index = 0; index  length; index += 1) { const value = array[index]; if (callback(value, index, array)) { return true; } } return false;}

俺们为各样值实行回调。若是在此外时候回来true,则脱离循环,整个艺术重临true。倘若循环终止而并未有进去到if语句里面(表明条件都不树立卡塔尔,则方法重回false。

测试

logOperation('some', [1, 2, 3, 4, 5], array = some(array, number = number === 5));

实践结果

{ operation: 'some', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: true}

.includes

includes方法的办事办法临近于some方法,但是includes不用回调,而是提供二个参数值来相比较成分。

[1, 2, 3].includes(3); // - true

实现

function includes(array, searchedValue){ return some(array, value = value === searchedValue)}

测试

logOperation('includes', [1, 2, 3, 4, 5], array = includes(array, 5));

推行结果

{ operation: 'includes', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: true}

东挪西凑、附加和反转数组.concat

concat(卡塔尔方法用于归并三个或七个数组,此办法不会纠正现成数组,而是重返一个新数组。

[1, 2, 3].concat([4, 5], 6, [7, 8]) // - [1, 2, 3, 4, 5, 6, 7, 8]

实现

function concat(array, ...values) { const result = [...array]; const { length } = values; for (let index = 0; index  length; index += 1) { const value = values[index]; if (Array.isArray(value)) { push(result, ...value); } else { push(result, value); } } return result;}

concat将数组作为第3个参数,并将未钦定个数的值作为第四个参数,这一个值能够是数组,也足以是其它类别的值。

首先,通过复制传入的数组创立result数组。然后,遍历values,检查该值是或不是是数组。假如是,则采纳push函数将其值增大到结果数组中。

push(result, value卡塔尔(قطر‎只会向数组追加为贰个成分。相反,通过使用举办操作符push(result,…value卡塔尔(قطر‎将数组的有着值增大到result数组中。在某种程度上,大家把数组扁平了生机勃勃层。

测试

logOperation('concat', [1, 2, 3, 4, 5], array = concat(array, 1, 2, [3, 4]));

试行结果

{ operation: 'concat', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: [ 1, 2, 3, 4, 5, 1, 2, 3, 4 ] }

.join

join(卡塔尔方法用于把数组中的全数因素放入三个字符串,成分是经过点名的相间符进行分隔的。

['Brian', 'Matt', 'Kate'].join(', ') // - Brian, Matt, Kate

实现

function join(array, joinWith) { return reduce( array, (result, current, index) = { if (index === 0) { return current; } return `${result}${joinWith}${current}`; }, '' )}

reduce的回调是美妙之处:reduce遍历所提供的数组并将结果字符串拼接在一块儿,在数组的值时期放置所需的分隔符(作为joinWith传递State of Qatar。

array[0]值需求部分古怪的拍卖,因为那时result是八个空字符串,而且我们也不指望分隔符(joinWith卡塔尔(قطر‎坐落于第三个因素前面。

测试

logOperation('join', [1, 2, 3, 4, 5], array = join(array, ', '));

奉行结果

{ operation: 'join', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: '1, 2, 3, 4, 5'}

.reverse

reverse(卡塔尔(قطر‎方法将数组中元素的职位颠倒,并重临该数组,该方法会改造原数组。

实现

function reverse(array) { const result = [] const lastIndex = array.length - 1; for (let index = lastIndex; index  -1; index -= 1) { const value = array[index]; result[lastIndex - index ] = value } return result;}

其思路非常粗略:首先,定义二个空数组,并将数组的结尾八个目录保存为变量(lastIndexState of Qatar。接着反过来遍历数组,将各种值保存在结果result中的(lastIndex

  • index卡塔尔地方,然后回到result数组。

测试

logOperation('reverse', [1, 2, 3, 4, 5], array = reverse(array));

推行结果

{ operation: 'reverse', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: [ 5, 4, 3, 2, 1 ]}

加上、删除和增添值.shift

shift(卡塔尔国方法从数组中剔除第一个因素,并再次来到该因素的值,此情势改进数组的尺寸。

[1, 2, 3].shift(); // - 1

实现

function shift(array) { const { length } = array; const firstValue = array[0]; for (let index = 1; index  length; index += 1) { const value = array[index]; array[index - 1] = value; } array.length = length - 1; return firstValue;}

先是保存数组的本来长度及其起初值,然后遍历数组并将各样值向下活动三个索引。完毕遍历后,更新数组的长短并回到起首值。

测试

logOperation('shift', [1, 2, 3, 4, 5], array = shift(array));

实践结果

{ operation: 'shift', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 2, 3, 4, 5 ], mutates: true, result: 1}

.unshift

unshift(State of Qatar方法将一个或多个成分增添到数组的起头,并再次来到该数组的新长度(该办法纠正原有数组State of Qatar。

[2, 3, 4].unshift(1); // - [1, 2, 3, 4]

实现

function unshift(array, ...values) { const mergedArrays = concat(values, ...array); const { length: mergedArraysLength } = mergedArrays; for (let index = 0; index  mergedArraysLength; index += 1) { const value = mergedArrays[index]; array[index] = value; } return array.length;}

首先将需求参与数组(作为参数字传送递的单个值卡塔尔(قطر‎和数组东挪西撮起来。这里需求小心的是,values放在第一位的,相当于放置在原始数组的如今。

接下来保留那几个新数组的尺寸并遍历它,将它的值保存在原始数组中,并掩瞒起头时的值。

测试

logOperation('unshift', [1, 2, 3, 4, 5], array = unshift(array, 0));

奉行结果

{ operation: 'unshift', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 0, 1, 2, 3, 4, 5 ], mutates: true, result: 6}

.slice

slice() 

办法重返一个新的数组对象,那意气风发对象是四个由begin和end决定的原数组的浅拷贝原始数组不会被退换。

slice会提取原数组中索引从begin到end的保有因素。

[1, 2, 3, 4, 5, 6, 7].slice(3, 6); // - [4, 5, 6]

兑现 (简单达成卡塔尔国

function slice(array, startIndex = 0, endIndex = array.length) { const result = []; for (let index = startIndex; index  endIndex; index += 1) { const value = array[index]; if (index  array.length) { push(result, value); } } return result;}

咱俩遍历数组从startIndex到endIndex,并将每一个值放入result。这里运用了那边的暗中同意参数,那样当未有传递参数时,slice方法只创制数组的别本。

瞩目:if语句确定保障只在原始数组中留存给定索引下的值时才步向result中。

测试

logOperation('slice', [1, 2, 3, 4, 5], array = slice(array, 1, 3));

实行结果

{ operation: 'slice', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4, 5 ], mutates: false, result: [ 2, 3 ]}

.splice

splice(State of Qatar方法通过删除或沟通现成成分或许原地增加新的因一向订正数组,并以数组格局重临被改变的剧情。此方法会改革原数组。

率先,钦点起首索引,然后钦点要删减多少个值,其他的参数是要插入的值。

const arr = [1, 2, 3, 4, 5];// 从位置0开始,删除2个元素后插入 3, 4, 5arr.splice(0, 2, 3, 4, 5);arr // - [3, 4, 5, 3, 4, 5]

实现

function splice( array, insertAtIndex, removeNumberOfElements, ...values) { const firstPart = slice(array, 0, insertAtIndex); const secondPart = slice(array, insertAtIndex + removeNumberOfElements); const removedElements = slice( array, insertAtIndex, insertAtIndex + removeNumberOfElements ); const joinedParts = firstPart.concat(values, secondPart); const { length: joinedPartsLength } = joinedParts; for (let index = 0; index  joinedPartsLength; index += 1) { array[index] = joinedParts[index]; } array.length = joinedPartsLength; return removedElements;}

其思路是在insertAtIndex和insertAtIndex + removeNumberOfElements上扩充一遍切割。那样,将原始数组切成三段。第大器晚成某个(firstPartState of Qatar和第三有个别(secondPart卡塔尔(قطر‎加个插入的要素结合为终极数组的剧情。

测试

logOperation('splice', [1, 2, 3, 4, 5], array = splice(array, 1, 3));

奉行结果

{ operation: 'splice', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 5 ], mutates: true, result: [ 2, 3, 4 ]}

.pop

pop(卡塔尔国方法从数组中除去最终二个成分,并回到该因素的值。此措施校勘数组的长度。

实现

function pop(array) { const value = array[array.length - 1]; array.length = array.length - 1; return value;}

率先,将数组的终极多少个值保存在叁个变量中。然后只需将数组的长短减弱1,从而去除最后三个值。

测试

logOperation('pop', [1, 2, 3, 4, 5], array = pop(array));

推行结果

{ operation: 'pop', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4 ], mutates: true, result: 5}

.push

push(卡塔尔(قطر‎方法将三个或多个成分加多到数组的终极,并重临该数组的新长度。

[1, 2, 3, 4].push(5); // - [1, 2, 3, 4, 5]

实现

function push(array, ...values) { const { length: arrayLength } = array; const { length: valuesLength } = values; for (let index = 0; index  valuesLength; index += 1) { array[arrayLength + index] = values[index]; } return array.length;}

第生龙活虎,我们保留原始数组的尺寸,以致在它们各自的变量中要加上的值。然后,遍历提供的值并将它们拉长到原始数组中。

测试

logOperation('push', [1, 2, 3, 4, 5], array = push(array, 6, 7));

执行结果

{ operation: 'push', arrayBefore: [ 1, 2, 3, 4, 5 ], arrayAfter: [ 1, 2, 3, 4,5, 6, 7 ], mutates: true, result: 7}

.fill

当我们想用一个占位符值填充一个空数组时,能够利用fill方法。如若想创建三个内定数量的null成分数组,能够如此做:

[...Array(5)].fill(null) // - [null, null, null, null, null]

实现

function fill(array, value, startIndex = 0, endIndex = array.length) { for (let index = startIndex; index  endIndex; index += 1) { array[index] = value; } return array;}

fill方法确实做的是替换钦点索引范围内的数组的值。若无提供范围,该办法将替换全数数组的值。

测试

logOperation("fill", [...new Array(5)], array = fill(array, 0));

实行结果

{ operation: 'fill', arrayBefore: [ undefined, undefined, undefined, undefined, undefined ], arrayAfter: [ 0, 0, 0, 0, 0 ], mutates: true, result: [ 0, 0, 0, 0, 0 ]}

扁平类

有的时候大家的数组会变嵌套两到三层,大家想要将它们扁,约等于减掉嵌套的水平。举个例子,想将具有值都放到顶层。为我们提供帮扶有八个新特色:flat和flatMap方法。

.flat

flat方法通过可内定深度值来减弱嵌套的深度。

[1, 2, 3, [4, 5, [6, 7, [8]]]].flat(1); // - [1, 2, 3, 4, 5, [6, 7, [8]]]

因为张开的纵深值是1,所以独有首先级数组是被扁平,别的的维持不改变。

[1, 2, 3, [4, 5]].flat(1) // - [1, 2, 3, 4, 5]

实现

function flat(array, depth = 0) { if (depth  1 || !Array.isArray(array)) { return array; } return reduce( array, (result, current) = { return concat(result, flat(current, depth - 1)); }, [], );}

首先,大家检查depth参数是还是不是低于1。即便是,这就代表未有何样要扁平的,大家应该简单地回去数组。

附带,我们检查数组参数是或不是归于数组类型,因为假使它不是,那么扁化就从不意义了,所以只回去那个参数。

大家们采纳了事情未发生前实现的reduce函数。从一个空数组开端,然后取数组的种种值并将其扁平。

留意,我们调用带有(depth - 1卡塔尔的flat函数。每回调用时,都依次减少depth参数,避防导致非常循环。扁平化实现后,将重临值来回加到result数组中。

测试

logOperation('flat', [1, 2, 3, [4, 5, [6]]], array = flat(array, 2));

执行结果

{ operation: 'flat', arrayBefore: [ 1, 2, 3, [ 4, 5, [Array] ] ], arrayAfter: [ 1, 2, 3, [ 4, 5, [Array] ] ], mutates: false, result: [ 1, 2, 3, 4, 5, 6 ]}

.flatMap

flatMap(卡塔尔方法首先选取映射函数映射每一个元素,然后将结果压缩成一个新数组。它与 map 和 深度值1的 flat 大约等同,但 flatMap 日常在统百分之十风流洒脱种艺术的成效稍稍高级中学一年级些。

在下边包车型大巴map方法中,对于各样值,只回去多少个值。那样,一个分包两个成分的数组在炫丽之后仍有四个因素。使用flatMap,在提供的回调函数中,能够回来三个数组,那么些数组稍后将被扁平。

[1, 2, 3].flatMap(value = [value, value, value]); // [1, 1, 1, 2, 2, 2, 3, 3, 3]

各样重回的数组都以扁平的,大家获取的不是一个嵌套了几个数组的数组,而是叁个包蕴9个因素的数组。

实现

function flatMap(array, callback) { return flat(map(array, callback), 1);}

先是选用map,然后将数组的结果数组扁平化大器晚成层。

测试

logOperation('flatMap', [1,2,3],array=flatMap(array,number=[number,number]));

施行结果

{ operation: 'flatMap', arrayBefore: [ 1, 2, 3 ], arrayAfter: [ 1, 2, 3 ], mutates: false, result: [ 1, 1, 2, 2, 3, 3 ]}

generator 类

最后三种艺术的异样之处在于它们重回生成器的方法。假若您不明白生成器,请跳过它们,因为你可能不会相当慢使用它们。

.values

values方法重回三个生成器,该生成器生成数组的值。

const valuesGenerator = values([1, 2, 3, 4, 5]);valuesGenerator.next(); // { value: 1, done: false }

实现

function values(array) { const { length } = array; function* createGenerator() { for (let index = 0; index  length; index += 1) { const value = array[index]; yield value; } } return createGenerator();}

第生机勃勃,我们定义createGenerator函数。在里边,我们遍历数组并生成每一个值。

.keys

keys方法重返二个生成器,该生成器生成数组的目录。

const keysGenerator = keys([1, 2, 3, 4, 5]);keysGenerator.next(); // { value: 0, done: false }

实现

function keys(array) { function* createGenerator() { const { length } = array; for (let index = 0; index  length; index += 1) { yield index; } } return createGenerator();}

贯彻完全相像,但那叁回,生成的是索引,实际不是值。

.entries

entry方法再次来到生成键值对的生成器。

const entriesGenerator = entries([1, 2, 3, 4, 5]);entriesGenerator.next(); // { value: [0, 1], done: false }

实现

function entries(array) { const { length } = array; function* createGenerator() { for (let index = 0; index  length; index += 1) { const value = array[index]; yield [index, value]; } } return createGenerator();}

相像的完成,但未来大家将引得和值结合起来,并在数组中变化它们。

总结

飞快利用数组的章程是成为一名佳绩开辟职员的根基。领悟她们之山东中华南理法高校程集团作的千头万绪是自个儿所知道的最棒的艺术。

原文:

上一篇:没有了