Henry Henry
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)

Henry

小学生中的前端大佬
  • JavaScript
  • TypeScript
  • Vue
  • ElementUI
  • React
  • HTML
  • CSS
  • 技术文档
  • GitHub 技巧
  • Nodejs
  • Chrome
  • VSCode
  • Other
  • Mac
  • Windows
  • Linux
  • Vim
  • VSCode
  • Chrome
  • iTerm
  • Mac
  • Obsidian
  • lazygit
  • Vim 技巧
  • 分类
  • 标签
  • 归档
  • 网站
  • 资源
  • Vue 资源
GitHub (opens new window)
  • JavaScript

    • js 编码指南
    • 日期使用斜杠 点 中划线分隔的不同
    • forEach 会改变原数组值吗
    • 前端表单验证常用的正则表达式 - reg
    • JS 如何取得 URL 里的参数
    • JavaScript 数组去重
    • JavaScript 循环中断研究与总结-关键字篇
    • JavaScript 循环中断研究与总结-用法篇
    • js 中的 Error
    • 跳出 forEach
    • Location 对象
    • Date 方法预览
    • Reg 正则中的问题
    • JavaScript toFixed() 方法
    • query 和 params 的使用区别
    • axios post 请求中下载文件流
    • 实用的 js 技巧
    • JS 之数组的几个不 low 操作
      • 扁平化 n 维数组
        • 终极篇
        • 开始篇
      • 去重
        • 终极篇
        • 开始篇
      • 排序
        • 终极篇
        • 开始篇
      • 最大值
        • 终极篇
        • 开始篇
      • 求和
        • 终极篇
        • 开始篇
      • 合并
        • 终极篇
        • 开始篇
      • 判断是否包含值
        • 终极篇
        • 开始篇
      • 类数组转化
        • 终极篇
        • 开始篇
      • 每一项设置值
        • 终极篇
        • 开始篇
      • 每一项是否满足
      • 有一项满足
      • 过滤数组
      • 对象和数组转化
      • 参考资料
    • 深入浅出深拷贝与浅拷贝
    • 如何实现一个深拷贝
    • 使用 iframe 中的一些问题
    • 在 js 中更好地使用数组
    • echarts 在坐标轴两侧各增加一格坐标
    • 从头认识js的事件循环模型
    • moment 根据周截至日算出指定月有几周及开始结束日期
    • 正则 reg 中 /number 的用法
    • 正则 reg 中 match 和 exec 异同
  • TypeScript

  • Vue

  • ElementUI

  • React

  • AntD

  • 前端
  • JavaScript
Henry
2019-03-12
目录
扁平化 n 维数组
终极篇
开始篇
去重
终极篇
开始篇
排序
终极篇
开始篇
最大值
终极篇
开始篇
求和
终极篇
开始篇
合并
终极篇
开始篇
判断是否包含值
终极篇
开始篇
类数组转化
终极篇
开始篇
每一项设置值
终极篇
开始篇
每一项是否满足
有一项满足
过滤数组
对象和数组转化
参考资料

JS 之数组的几个不 low 操作

本文主要从应用来讲数组 api 的一些骚操作;

如一行代码扁平化 n 维数组、数组去重、求数组最大值、数组求和、排序、对象和数组的转化等

# 扁平化 n 维数组

# 终极篇

;[1, [2, 3]].flat(2) //[1,2,3]
;[1, [2, 3, [4, 5]].flat(3) //[1,2,3,4,5]
;[1, [2, 3, [4, 5]]].toString() //'1,2,3,4,5'
;[1[2, 3, [4, 5[...]].flat(Infinity) //[1,2,3,4...n]
1
2
3
4

Array.flat(n)是 ES10 扁平数组的 api, n 表示维度, n 值为 Infinity 时维度为无限大

# 开始篇

function flatten(arr) {
  while (arr.some(item => Array.isArray(item))) {
    arr = [].concat(...arr)
  }
  return arr
}
flatten([1, [2, 3]]) //[1,2,3]
flatten([1, [2, 3, [4, 5]]]) //[1,2,3,4,5]
1
2
3
4
5
6
7
8

实质是利用递归和数组合并方法 concat 实现扁平

# 去重

# 终极篇

Array.from(new Set([1, 2, 3, 3, 4, 4])) //[1,2,3,4]
;[...new Set([1, 2, 3, 3, 4, 4])] //[1,2,3,4]
1
2

set 是 ES6 新出来的一种一种定义不重复数组的数据类型

Array.from 是将类数组转化为数组

... 是扩展运算符, 将 set 里面的值转化为字符串

# 开始篇

Array.prototype.distinct = nums => {
  const map = {}
  const result = []
  for (const n of nums) {
    if (!(n in map)) {
      map[n] = 1
      result.push(n)
    }
  }
  return result
}
;[1, 2, 3, 3, 4, 4].distinct() //[1,2,3,4]
1
2
3
4
5
6
7
8
9
10
11
12

取新数组存值, 循环两个数组值相比较

# 排序

# 终极篇

;[1, 2, 3, 4].sort((a, b) => a - b) // [1, 2,3,4],默认是升序
;[1, 2, 3, 4].sort((a, b) => b - a) // [4,3,2,1] 降序
1
2

sort 是 js 内置的排序方法, 参数为一个函数

# 开始篇

冒泡排序:

Array.prototype.bubbleSort = function() {
  let arr = this,
    len = arr.length
  for (let outer = len; outer >= 2; outer--) {
    for (let inner = 0; inner <= outer - 1; inner++) {
      if (arr[inner] > arr[inner + 1]) {
        //升序
        ;[arr[inner], arr[inner + 1]] = [arr[inner + 1], arr[inner]]
        console.log([arr[inner], arr[inner + 1]])
      }
    }
  }
  return arr
}
;[(1, 2, 3, 4)].bubbleSort() //[1,2,3,4]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

选择排序

Array.prototype.selectSort = function() {
  let arr = this,
    len = arr.length
  for (let i = 0, len = arr.length; i < len; i++) {
    for (let j = i, len = arr.length; j < len; j++) {
      if (arr[i] > arr[j]) {
        ;[arr[i], arr[j]] = [arr[j], arr[i]]
      }
    }
  }
  return arr
}
;[(1, 2, 3, 4)].selectSort() //[1,2,3,4]
1
2
3
4
5
6
7
8
9
10
11
12
13

# 最大值

# 终极篇

Math.max(...[1, 2, 3, 4]) //4
Math.max.apply(this, [1, 2, 3, 4]) //4
;[(1, 2, 3, 4)].reduce((prev, cur, curIndex, arr) => {
  return Math.max(prev, cur)
}, 0) //4
1
2
3
4
5

Math.max()是 Math 对象内置的方法, 参数是字符串;

reduce 是 ES5 的数组 api, 参数有函数和默认初始值;

函数有四个参数, pre(上一次的返回值), cur(当前值), curIndex(当前值索引), arr(当前数组)

# 开始篇

先排序再取值

# 求和

# 终极篇

;[1, 2, 3, 4].arr.reduce(function(prev, cur) {
  return prev + cur
}, 0) //10
1
2
3

# 开始篇

function sum(arr) {
  var len = arr.length
  if (len == 0) {
    return 0
  } else if (len == 1) {
    return arr[0]
  } else {
    return arr[0] + sum(arr.slice(1))
  }
}
sum([1, 2, 3, 4]) //10
1
2
3
4
5
6
7
8
9
10
11

利用 slice 截取改变数组, 再利用递归求和

# 合并

# 终极篇

[1, 2, 3, 4].concat([5, 6]) //[1,2,3,4,5,6]
[...[1, 2, 3, 4], ...[4, 5]] //[1,2,3,4,5,6]
let arrA = [1, 2],
  arrB = [3, 4]
Array.prototype.push.apply(arrA, arrB)) //arrA值为[1,2,3,4]
1
2
3
4
5

# 开始篇

let arr = [1, 2, 3, 4]
;[5, 6].map(item => {
  arr.push(item)
})
//arr值为[1,2,3,4,5,6],注意不能直接return出来,return后只会返回[5,6]
1
2
3
4
5

# 判断是否包含值

# 终极篇

[1, 2, 3].includes(4) //false
[1, 2, 3].indexOf(4) //-1 如果存在换回索引
[1, 2, 3].find((item) => item === 3)) //3 如果数组中无值返回undefined
[1, 2, 3].findIndex((item) => item === 3)) //2 如果数组中无值返回-1
1
2
3
4

includes(), find(), findIndex()是 ES6 的 api

# 开始篇

;[1, 2, 3].some(item => {
  return item === 3
}) //true 如果不包含返回false
1
2
3

# 类数组转化

# 终极篇

Array.prototype.slice.call(arguments) //arguments是类数组(伪数组)
Array.prototype.slice.apply(arguments)
Array.from(arguments)[...arguments]
1
2
3

类数组: 表示有 length 属性, 但是不具备数组的方法

call, apply: 是改变 slice 里面的 this 指向 arguments, 所以 arguments 也可调用数组的方法

Array.from 是将类似数组或可迭代对象创建为数组

... 是将类数组扩展为字符串, 再定义为数组

# 开始篇

Array.prototype.slice = function(start, end) {
  var result = new Array()
  start = start || 0
  end = end || this.length //this指向调用的对象,当用了call后,能够改变this的指向,也就是指向传进来的对象,这是关键
  for (var i = start; i < end; i++) {
    result.push(this[i])
  }
  return result
}
1
2
3
4
5
6
7
8
9

# 每一项设置值

# 终极篇

;[1, 2, 3].fill(false) //[false,false,false]
1

fill 是 ES6 的方法

# 开始篇

;[1, 2, 3].map(() => 0)
1

# 每一项是否满足

;[1, 2, 3].every(item => {
  return item > 2
}) //false
1
2
3

every 是 ES5 的 api, 每一项满足返回 true

# 有一项满足

;[1, 2, 3].some(item => {
  return item > 2
}) //true
1
2
3

some 是 ES5 的 api, 有一项满足返回 true

# 过滤数组

;[1, 2, 3].filter(item => {
  return item > 2
}) //[3]
1
2
3

filter 是 ES5 的 api, 返回满足添加的项的数组

# 对象和数组转化

Object.keys({
  name: '张三',
  age: 14
}) //['name','age']
Object.values({
  name: '张三',
  age: 14
}) //['张三',14]
Object.entries({
  name: '张三',
  age: 14
}) //[[name,'张三'],[age,14]]
Object.fromEntries([name, '张三'], [age, 14]) //ES10的api,Chrome不支持 , firebox输出{name:'张三',age:14}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 参考资料

  • JS 之数组的几个不 low 操作(3) - 前端小而全的知识归纳 - SegmentFault 思否 (opens new window)
编辑 (opens new window)
#Js
上次更新: 12/31/2020, 7:24:06 AM
实用的 js 技巧
深入浅出深拷贝与浅拷贝

← 实用的 js 技巧 深入浅出深拷贝与浅拷贝→

最近更新
01
搭配 Jenkins 实现自动化打包微前端多个项目
09-15
02
自动化打包微前端多个项目
09-15
03
el-upload 直传阿里 oss 并且显示自带进度条和视频回显封面图
06-05
更多文章>
0 comments
Anonymous
Markdown is supported

Be the first person to leave a comment!

Theme by Vdoing | Copyright © 2017-2025 HenryTSZ | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式