25个JavaScript数组方法代码示例

已有人阅读此文 - - admin

25个JavaScript数组方法代码示例知识,25个JavaScript数组方法代码示例图片 25个JavaScript数组方法代码示例内容,25个JavaScript数组方法代码示例介绍,25个JavaScript数组方法代码示例,25个,JavaScript,数组,方法,代码,示例,Jav的正文:

25个JavaScript数组方法代码示例包含:你越早落后,你就必须赶上更多的时间。 红色括号给出了一个基本示例,表示另一个括号必须在附近。 (马丁·戈尔丁) 绝对有必要做正确的事情。 PoT是一个熟悉的概念,所以很容易理解。 (奥斯特霍特) bootstrap是一个前端框架 当你完成了JavaSE和JavaEE的学习后, 可以申请发布内容 用代码行来评估软件开发的进度就像用权重来评估飞机建造的进度一样。 软件通常在beta测试完成后不久发布。 移动到C++或许多其他编程语言中的一种。 有三种:懒惰、易怒和傲慢。 集成了各种键盘命令和功能。 (Gerald Weinberg) 将这些库集成到ruby on rails框架中,以扩展代码的功能。 在编程时要牢记这一想法:就像将来要维护你的代码的人是一个知道你住在哪里的残忍的疯子。 这些允许更快和更清晰的编码。 如果一切都好,你就失业了。 你写的任何超过六个月没读过的代码,就像你再看别人的代码一样。 25个JavaScript数组方法代码示例介绍的方法与命令流程等可以帮助到读者。

25个JavaScript数组方法代码示例例图

JavaScript 数组的力量隐藏在数组方法中。

把数组转换为字符串

JavaScript 方法 toString() 把数组转换为数组值(逗号分隔)的字符串。

搜罗了目前 Javascript 数组所有的方法,迷失道路的小伙伴可以直接查看页面右边的目录

数组创建

const arr1 = [1, 2, 3]; // [1, 2, 3]
const arr2 = Array(); // []
const arr3 = Array(2); // [undefined, undefined]
const arr4 = Array(1,2,3);  // [1, 2, 3]

Array.from: 将一个对象转化成数组

/*
 *  第一个参数:被转化的数组
 *  第二个参数:对每个元素进行处理,将处理后的结果放入返回的数组(类似于map)
 *  第三个参数:用来绑定this
 */

// 当参数为一个Object类型时,需要有length属性,用来指定数组长度,默认为0
Array.from({ 2: '2', a: 'a', 0: '0', length: 4})  // ['0', undefined, 2: undefined]
Array.from({ 2: '2', a: 'a', 0: '0', length: 2})  // ['0', undefined]
Array.from({ 2: '2', a: 'a', 0: '0', length: 2}, v => v || '')   // ['0', '']
Array.from('hello') // ['h', 'e', 'l', 'l', 'o']

Array.isArray: 判断传递的值是否是一个 Array 类型

Array.isArray([1,2,3])  // true
Array.isArray({a: 'a'}) // false
Array.isArray('hello')  // false
Array.isArray(Array(3)) // true
Array.isArray(null)     // false

Array.of: 把所有的参数放到一个数组中返回

const arr1 = Array.of(1, 2, 3); // [1, 2, 3]
const arr1 = Array.of();        // []

Array.apply: 创建空数组

/*
 *  第一个参数:用来绑定this
 *  第二个参数:数组参数(参考Array.from的第一个参数)
 */

Array.apply(null, {1:'1', length: 2}) // [undefined, '1']

Array.apply(null, {length: 2} 与 Array(2) 的区别:

  • Array(2) 只有 length,没有索引和元素,所以不能用 map
const arr1 = Array.apply(null, {length: 2}) // [undefined, undefined]
const arr2 = Array(2) // [empty x 2]

1 in arr1 // true
1 in arr2 // false

arr1.map(v => 1) // [1, 1]
arr2.map(v => 1) // [empty x 2]

concat: 合并多个数组并返回一个新数组(原有数组不变)

const arr1 = [1, 2]
const arr2 = ['a', 'b']
const arr3 = ['hello']

const arr4 = arr1.concat(arr2, arr3)  // [1, 2, 'a', 'b', 'hello']

copyWithin: 从数组的指定位置拷贝元素到另一个指定位置

/*
 *  第一个参数:复制的目标位置
 *  第二个参数:复制的开始位置(闭区间)
 *  第三个参数:复制的结束位置(开区间)
 */

const arr = [1,2,3,4,5,6]
arr.copyWithin(4, 1, 3) // [1,2,3,4,2,3]

entries: 返回一个数组的迭代对象(Iterator)

const arr = [1,2,3]
const it = arr.entries()
console.log(it.next())  // {value: [0,1], done: false}
console.log(it.next())  // {value: [1,2], done: false}
console.log(it.next())  // {value: [2,3], done: false}
console.log(it.next())  // {value: undefined, done: true}

every: 对数组中所有的元素进行检查,返回布尔值

some: 和every类似,every是需要所有元素都满足条件,而some只要有满足的就会返回true

const arr = [1,2,3]
arr.every(v => { console.log(v); return v < 10}) // 1 2 3 true
arr.every(v => { console.log(v); return v < 2})  // 1 2 false
arr.some(v => { console.log(v); return v < 2})  // 1 true

fill: 用一个固定值替换数组中的元素

/*
 *  第一个参数:填充的值
 *  第二个参数:填充的开始位置(闭区间)
 *  第三个参数:填充的结束位置(开区间)
 */

const arr = [1,2,3,4,5,6]
arr.fill(0, 1, 3) // [1,0,0,4,5,6]
Array(2).fill(0)  // [0,0]

filter: 创建一个新数组,返回原数组中满足条件的所有元素

const arr1 = [
  { age: 10, name: '10'},
  { age: 23, name: '23'},
  { age: 16, name: '16'},
  { age: 11, name: '11'},
  { age: 37, name: '37'}
]
arr1.filter(v => v.age < 18)

// 输出
/* [
 *   { age: 10, name: '10'},
 *   { age: 16, name: '16'},
 *   { age: 11, name: '11'}
 * ]
 */

find: 返回数组中第一个满足条件的元素

findIndex: 返回数组中第一个满足条件的元素的索引值

const arr1 = [
  { age: 10, name: '10'},
  { age: 23, name: '23'},
  { age: 16, name: '16'},
  { age: 11, name: '11'},
  { age: 37, name: '37'}
]
arr1.find(v => v.age > 18)  // { age: 23, name: '23'}

flat: 创建一个新数组,扁平化原嵌套数组,参数为扁平的层数,该方法会移除空项

const arr1 = [1, , [2, [3, , [4]]]]
arr.flat()      // [1,2,[3, , [4]]]
arr.flat(2)     // [1,2,3,[4]]
arr.flat(3)     // [1,2,3,4]
arr.toString()  // '1,,2,3,,4'

flatMap: 和 map 相近,但是会将返回结果压平一层

const arr1 = [1,2,3]
arr1.map(v => [v * 2])    // [[2], [4], [6]]
arr1.flatMap(v => [v * 2]) // [2, 4, 6]

forEach: 遍历数组中的每一个元素

const arr1 = [1,2,3]
arr1.forEach(v => console.log(v))  // 1,2,3

includes: 判断一个数组中是否包含一个元素

const obj = {id: 2, value: '2'}
const arr = [
  obj,
  'hello',
  {id: 1, value: '1'}
]

arr.includes({id: 1, value: '1'}) // false
arr.includes(obj) // true
arr.includes('hello') // true

indexOf: 找到满足条件的元素的索引值,第一个参数是开始寻找的位置

lastIndexOf: 寻找顺序与indexOf相反

findIndex 的能力比 indexOf 更强,findIndex 相当于一个 for 循环,可以进行逻辑处理和判断,而 indexOf 能力较弱

const arr1 = ['a', 'b', 'c','b']
arr1.indexOf('b') // 1
arr1.lastIndexOf('b') // 3

join: 将元素连接成一个字符串,并用分隔符分割(第一个参数),元素会执行 toString

const arr = [1, 'b', {c: 2}, [3,4]]
arr.join(' & ') // "1 & b & [object Object] & 3,4"

keys: 和 entries 类似,但是返回的为 索引,而不再是 key/value

values: 和 entries 类似,但是返回的为 值,而不再是 key/value

const arr = [1,2,3]
const it = arr.keys()
console.log(it.next())  // {value: 0, done: false}
console.log(it.next())  // {value: 1, done: false}
console.log(it.next())  // {value: 2, done: false}
console.log(it.next())  // {value: undefined, done: true}

map: 返回一个新数组,数组中的元素为原数组经过处理后的值

const arr1 = [{id:1}, {id:2}, {id: 3}]
arr1.map(v => v.id) // [1, 2, 3]

pop: 删除原数组的最后一个元素

push: 在原数组的末尾添加一个元素

shift: 删除原数组的第一个元素

unshift: 在原数组开头添加一个元素

const arr = [1,2,3]
arr.pop()       // 3; arr: [1,2]
arr.shift()     // 1; arr: [2]
arr.push(3)     // 2; arr: [2,3]
arr.unshift(4)  // 2; arr: [4,2,3]

reduce: 接受一个累加器,数组中的每个值开始缩减,最终计算为一个值

reduceRight: 功能和reduce一样,只是是从末尾向前做累加

const arr = [1,2,3]
function getSum(total, currentValue, currentIndex, arr) {
  return total + currentValue;
}
arr.reduce(getSum, 10)  // 16; arr: [1,2,3]

reverse: 颠倒原数组中元素的顺序

const arr = [1,2,3]
arr.reverse() // [3,2,1]

slice: 提取数组中的子串到新数组

splice: 删除原数组中的子串

const arr = [1,2,3,4,5]
arr.slice(2,4)  // [3,4]; arr: [1,2,3,4,5]
arr.splice(1,2) // [2,3]; arr: [1,4,5]

sort

const asc = (a,b) => a - b
const des = (a,b) => b - a
const arr = [3,1,4,2,7]
arr.sort(asc) // [1, 2, 3, 4, 7]
arr.sort(des) // [7, 4, 3, 2, 1]

 

0人点赞

Javascript

 

Fundebug经授权转载,版权归原作者所有。https://www.cnblogs.com/fundebug/p/understand-25-javascript-array-methods-by-implementing-them.html

要在给定数组上使用方法,只需要通过[].方法名即可,这些方法都定义在 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 每次执行后的返回值(包括 undefined)组合起来形成一个新数组。

实现

    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;
    }

获取每个值并检查所提供的回调函数是否返回truefalse,然后将该值添加到新创建的数组中,或者适当地丢弃它。

注意,这里对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 ] 
    }

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 [Fundebug][https://www.fundebug.com/?utm_source=xiaozhi]。

.reduce

reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值reduce() 方法接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce() 的数组

确切地说,如何计算该值是需要在回调中指定的。来看呓使用reduce的一个简单的例子:对一组数字求和:

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

注意这里的回调接受两个参数:sumnumber。第一个参数总是前一个迭代返回的结果,第二个参数在遍历中的当前数组元素。

这里,当咱们对数组进行迭代时,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;
    }

咱们创建了两个变量accstartAtIndex,并用它们的默认值初始化它们,分别是参数initValue0

然后,检查initValue是否是undefined。如果是,则必须将数组的第一个值设置为初值,为了不重复计算初始元素,将startAtIndex设置为1

每次迭代,reduce方法都将回调的结果保存在累加器(acc)中,然后在下一个迭代中使用。对于第一次迭代,acc被设置为initValuearray[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函数返回真实值(强制为true)的值。如果找到这样的元素,findIndex会立即返回该元素的索引。如果回调从不返回真值,或者数组的length0,则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

findfindIndex的唯一区别在于,它返回的是实际值,而不是索引。实际工作中,咱们可以重用已经实现的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() 方法返回指定元素在数组中的最后一个的索引,如果不存在则返回 -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类似,但是没有执行回调,而是比较valuesearchedValue。如果比较结果为 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将数组作为第一个参数,并将未指定个数的值作为第二个参数,这些值可以是数组,也可以是其他类型的值。

首先,通过复制传入的数组创建 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传递)。

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;
    }

其思路很简单:首先,定义一个空数组,并将数组的最后一个索引保存为变量(lastIndex)。接着反过来遍历数组,将每个值保存在结果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() 方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。

    [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 决定的原数组的浅拷贝(包括 begin,不包括end)原始数组不会被改变。

slice 会提取原数组中索引从 begin 到 end 的所有元素(包含 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;
    }

咱们遍历数组从startIndexendIndex,并将每个值放入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() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

首先,指定起始索引,然后指定要删除多少个值,其余的参数是要插入的值。

    const arr = [1, 2, 3, 4, 5];
    // 从位置0开始,删除2个元素后插入 3, 4, 5
    arr.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;
    }

其思路是在insertAtIndexinsertAtIndex + removeNumberOfElements上进行两次切割。这样,将原始数组切成三段。第一部分(firstPart)和第三部分(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 ]
    }

扁平类

有时咱们的数组会变嵌套两到三层,咱们想要将它们扁,也就是减少嵌套的程度。例如,想将所有值都放到顶层。为咱们提供帮助有两个新特性:flatflatMap 方法。

.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();
    }

同样的实现,但现在咱们将索引和值结合起来,并在数组中生成它们。

总结

高效使用数组的方法是成为一名优秀开发人员的基础。了解他们内部工作的复杂性是我所知道的最好的方法。

代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 [Fundebug][https://www.fundebug.com/?utm_source=xiaozhi]。

原文:https://dev.to/bnevilleoneill/understand-array-methods-by-implementing-them-all-of-them-iha

https://www.jianshu.com/p/98ca018689d8

125个JavaScript数组方法代码示例系部分转载自网络,如有对程序员或作者侵犯,请联系我们立即删除,另:本文仅代表作者个人观点,与本网站无关。

225个JavaScript数组方法代码示例这篇文章的原创性以及文中对于编程运维专业度的陈述文字 和内容未经本站证实,对本文以及其中全部或者部分内容及图片的有效性、文字的真实性、完整性、及时性本站不作任何保证或承诺以及推荐,本站非盈利,有对图片文字不适的请程序员及读者仅作参考并自行核实相关内容

3这篇25个JavaScript数组方法代码示例的文章,涉及的25个,JavaScript,数组,方法,代码,示例,Jav命令,变量,函数,代码,类,库等皆是代称