对前端开发中常使用的函数方法的一个小总结

1,212 阅读11分钟
第一次在掘金发文章,好紧张啊~~~~(>_<)~~~~

箭头函数 MDN地址

先说一下箭头函数,因为下面默认都使用箭头函数,基本上不会出现function字样。

// 仅做举例使用哈

// 原始函数
function json2string(json){
  return JSON.stringify(json)
}

// 一级简写: 创建一个变量,并使这个变量等于一个箭头函数
const json2string = (json) => {
  return JSON.stringify(json)
} 

// 二级简写:当函数只有一个参数的时候,可以省略参数括号
const json2string = json => {
  return JSON.stringify(json)
}

// 三级简写: 当函数表达式只有一行的时候,可以省略return和{}
const json2string = json => JSON.stringify(json)


// 感谢@blacker2018大佬提醒,本例的四级简写

const json2string = JSON.stringify


// 例外:当函数没有参数的时候不能省略()
const helloWorld = () => 'hello world!'

上面是箭头函数的基本用法,另外说两句:

​ 1, 箭头函数没有自己的this

​ 2, 箭头函数的this指向从自身像外层找所能找到的第一个使用function声明的函数(见例1)

​ 3, 如果一直找到最顶层都没有function声明的函数,this指向window

​ 3, 9021年了,多使用箭头函数吧,毕竟好处那么多,代码简洁那么多

例1:

export default {
  name: 'test',
  data(){ // 这里不能用箭头函数,会改变this指向,请注意
    return {
      count: 0
    }
  },
  mounted(){ // 同理,不能箭头函数
    this.$axios({...}).then(res => this.count = res.count)
  }
}

啰嗦一句,既然用了箭头函数,就不要存 this 不然代码会让后来人吐槽的

好了,BB了半天,正文开始了。

操作数组的一些常用方法

filter() MDN地址

filter的中文解释是过滤,功能也显而易见,在一个数组中过滤出满足要求的数据,并返回一个由所有满足条件的数据组成的数组

let arr = array.filter(callback[, thisObject]);

  • callback: 要对每个数组元素执行的回调函数。函数有三个参数:currentElement, currentIndex, currentArray
    • currentElement 当前元素
    • currentIndex 当前元素的下标 如用不到,可以省略
    • currentArray 当前元素所在的数组(也就是当前被遍历的数组) 用不到可以省略
  • thisObject : 在执行回调函数时定义的this对象。

e.g.1 找出一个数组中所有大于3的数字

let arr = [1,2,3,4,5,6,7,8,9]
let arr2 = arr.filter(ele => ele > 3)

e.g.2 过滤数据数据中的所有disabledtrue的数据

const data = [
  {
    title: 'test1',
    disabled: false,
  },
  /*...省略100个*/
  {
    title: 'test100',
    disabled: true,
  }
]
const disabledList = data.filter(ele => ele.disabled)

e.g.3 这个很重要,还是上面的数据,需求要实现找出所有disabledtrue的数据的title

const disabledList = data.filter(ele => ele.disabled && ele.title) // 这样可以吗? false. 因为filter 不会执行 第一个条件之后的所有条件

难道这个需求就不能实现了吗?非也。接着往下看

map() MDN地址

这里的map不是“地图”的意思,而是指“映射”。map函数类似于上面的filter一样,接收一个函数,对数组中的每个元素执行相同的操作,接收一个并返回一个由所有满足条件的数据组成的数组

let newArray = array.map(callback[, thisObject]);

  • callback: 要对每个数组元素执行的回调函数。函数有三个参数:currentElement, currentIndex, currentArray callback函数如果不写return 默认return undefined
    • currentElement 当前元素
    • currentIndex 当前元素的下标 如用不到,可以省略
    • currentArray 当前元素所在的数组(也就是当前被遍历的数组) 用不到可以省略
  • thisObject : 在执行回调函数时定义的this对象。

e.g.1 上面filter不能实现的功能,现在配合map实现以下

const data = [
  {
    title: 'test1',
    disabled: false,
  },
  /*...省略100个*/
  {
    title: 'test100',
    disabled: true,
  }
]
// map 函数 当条件不满足时会return undefined 再filter过滤一下
const disabledList = data.map(ele => ele.disabled && ele.title).filter(Boolean) 

e.g.2

组合数据,这个例子主要是描述一种业务场景,可以看到data中的product字段从个人理解的意义上讲,price应该和title && author是一个级别的。现在我们就实现我们的想法

const data = [
  {
    title: 'egg',
    author: 'chicken',
    product: {
      price: 100,
      age: 2
    }
  },
  {
    title: 'dog',
    author: 'dog',
    product: {
      price: 1000,
      age: 0.5
    }
  }
]

const newArray = data.map(ele => {
  return {
    ...ele,
    ...ele.product || {} // 兼容没有product情况
  }
})

// 上面的函数得到的结果就满足了我们自身的需求 ...扩展运算符后面会讲
{
    title: 'egg',
    author: 'chicken',
    price: 100,
    age: 2
    product: {
	  price: 100,
      age: 2
    }
  }

forEach() MDN地址

forEach函数类似于上面的map一样,接收一个函数,对数组中的每个元素执行相同的操作,和filter/map不同的是 forEach 没有返回值 forEach()对于空数组是不会执行回调函数的

array.forEach(callback[, thisObject]);

  • callback: 要对每个数组元素执行的回调函数。函数有三个参数:currentElement, currentIndex, currentArray
    • currentElement 当前元素
    • currentIndex 当前元素的下标 如用不到,可以省略
    • currentArray 当前元素所在的数组(也就是当前被遍历的数组) 用不到可以省略
  • thisObject : 在执行回调函数时定义的this对象。
const data = [
  {
    title: 'test1',
    disabled: false,
  },
  /*...省略100个*/
  {
    title: 'test100',
    disabled: true,
  }
]
// map 函数 当条件不满足时会return undefined 再filter过滤一下
const disabledList = data.map(ele => ele.disabled && ele.title).filter(Boolean) 


/***************************************************/
// 上面的例子使用了filter和map两个遍历 使用forEach一遍就可以实现 更高效

let arr = []
data.forEach(ele =>{
  if(ele.disabled) arr.push(ele.title)
})

some() MDN地址

some中文意思是一些,在JS中表示数组中当有一个数据满足条件时返回true

some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。

some接收一个函数作为参数,函数有三个参数:

  • current 当前元素
  • index 当前下标
  • array 被循环的数组

e.g.1

const data = [1,2,3,4,5,6,8]
console.log(data.some(ele => ele > 4)) // true
console.log(data.some(ele => ele < 4)) // true
console.log(data.some(ele => ele > 8)) // false
console.log(data.some(ele => ele >= 2)) // true
console.log(data.some(ele => ele < 1)) // false

e.g.2

const data = [
  { id: 2, count: 200 },
  { id: 4, count: 300 },
  { id: 6, count: 100 },
  { id: 8, count: 700 }, 
]
console.log(data.some(ele => ele.count > 700)) // false
console.log(data.some(ele => ele.count > 600)) // true

every() MDN地址

every()是对数组中每一项运行给定函数,如果该函数对每一项返回true, 则返回true。

every接收一个函数作为参数,函数有三个参数:

  • current 当前元素
  • index 当前下标
  • array 被循环的数组
const data = [
  { id: 2, count: 200 },
  { id: 4, count: 300 },
  { id: 6, count: 100 },
  { id: 8, count: 700 }, 
]
console.log(data.every(ele => ele.count > 700)) // false
console.log(data.every(ele => ele.count < 900)) // true

reduce() MDN地址

arr.reduce(callback,[initialValue])
  • callback (执行数组中每个值的函数,包含四个参数)
    • previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
    • currentValue (数组中当前被处理的元素)
    • index (当前元素在数组中的索引)
    • array (调用 reduce 的数组)
  • initialValue (作为第一次调用 callback 的第一个参数。)
// 经典面试题: 使用reduce同时实现map和filter
// 例子: 找出所有double后大于50的数
const doubledOver50 = num => num.reduce((finalList, ele) => {
  const number = ele * 2
  if (number > 50) {
    finalList.push(ele)
  }
  return finalList
}, [])
doubledOver50(numbers) // [30, 40]

** reduce还有很多妙用,可以掘金搜一下哈

flat() MDN地址

这个是ES10的方法,实现数组扁平化,flat函数接收一个值指定要提取嵌套数组的结构深度,默认值为 1,返回一个包含将数组与子数组中所有元素的新数组。

由于是ES10的方法,使用的话需要考虑一下兼容性问题,贴上MDN地址:Array.prototype.flat()

let arr1 = [1, 2, [3, 4]];
arr1.flat();  // [1, 2, 3, 4]

let arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat(); // [1, 2, 3, 4, [5, 6]]

let arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2); // [1, 2, 3, 4, 5, 6]

//使用 Infinity 作为深度,展开任意深度的嵌套数组
arr3.flat(Infinity); // [1, 2, 3, 4, 5, 6]

扁平化与空项

flat() 方法会移除数组中的空项:

let arr4 = [1, 2, , 4, 5];
arr4.flat(); // [1, 2, 4, 5]

indexOf() MDN地址

indexOf()接收一个参数,并查找该元素在数组中的下标,遍历方向是从前向后遍历

let arr = [1,2,3,4,5,6,7]

const index = arr.indexOf(2) // 1

lastIndexOf() MDN地址

lastIndexOf()接收一个参数,并查找该元素在数组中的下标, 与indexOf不同的是遍历方向是从后向前遍历

let arr = [1,2,3,4,5,2,7]
const index = arr.lastIndexOf(2) // 5

find() MDN地址

find()找到数组中第一个符合条件的数据

find()接收一个函数作为参数, 函数的可选参数有

  • currentValue
  • index
  • arr

e.g.1:

let students = [
  { name: 'tom', age: 18 },
  { name: 'jeck', age: 20 },
  { name: 'bob', age: 19 }
]

let monitor = students.find(ele => ele.age > 18) // {name: 'jeck', age: 20}   [返回第一个符合条件的数据并结束循环]

findIndex() MDN地址

查找第一个符合条件的元素的下标,和find的区别就是find返回元素, findIndex返回下标

array.findIndex(callback, thisValue)
  • callback: 要对每个数组元素执行的回调函数。函数有三个参数:currentElement, currentIndex, currentArray
    • currentElement 当前元素
    • currentIndex 当前元素的下标 如用不到,可以省略
    • currentArray 当前元素所在的数组(也就是当前被遍历的数组) 用不到可以省略
  • thisValue : 在执行回调函数时定义的this对象。
let students = [
  { name: 'tom', age: 18 },
  { name: 'jeck', age: 20 },
  { name: 'bob', age: 19 }
]

let monitor = students.findIndex(ele => ele.age > 18) // 1 [返回第一个符合条件的数据的下标并结束循环]

操作对象的一些常用方法

Object.assign() MDN地址

Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

工作中用的最多的就是合并两个对象了,但是大多数情况下可以使用扩展运算符代替

对于Object.assign()是否能实现深拷贝,答案是否。具体原因点我

下面的例子仅仅只是介绍一下对象合并

let obj1 = { a: 1 }
let obj2 = { b:2 }
let obj3 = Object.assign(obj1, obj2) // {a: 1, b: 2}
let obj4 = Object.assign({}, obj1, obj2, obj3) // {a: 1, b: 2}

// 注意:对象的合并是从右向左进行,在上面的例子中,如果obj2中有和obj3一样的key 那么obj2中key对应的val会被obj3中对应的val覆盖掉

Object.keys() MDN地址

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。

//  数组
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']

// 类数组对象
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']

// 随机键排序的类数组对象
var anObj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.keys(anObj)); // console: ['2', '7', '100']


通常使用Object.keys()代替for...in来遍历对象

let obj = {
  a: 1,
  b: 2
}
let keys = Object.keys(obj).map(ele => ele += 'aaaaa' /* 可以分别对每个key做一些改造 */)

Object.values() MDN地址

Object.values()方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。

var obj = { foo: 'bar', baz: 42 };
console.log(Object.values(obj)); // ['bar', 42]

// 类数组对象
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']

// 随机键排序的类数组对象
var an_obj = { 100: 'a', 2: 'b', 7: 'c' };
console.log(Object.values(an_obj)); // ['b', 'c', 'a']

通常使用Object.values()代替for...in来遍历对象取value

let obj = {
  a: 1,
  b: 2
}
let values = Object.values(obj).map(ele => ele++ /* 可以分别对每个value做一些改造 */)


扩展运算符(…) MDN地址

在开发工作中,很多场景下都可以使用简化代码,下面列了一些使用场景

  • Math.max (求数组最大值)

    // e.g.1 求数组最大值
    let data = [1,2,3,4,5,6,7,8]
    const big = Math.max(...data) // 8
    
    // e.g.2 取库存量最多商品的库存
    let data = [
      {
        name: '橘子',
        stock: 100
      },
      {
        name: '橙子',
        stock: 300
      },
      {
        name: '苹果',
        stock: 700
      }
    ]
    
    // 结合map使用(map返回一个新数组)
    const big = Math.max(...data.map(ele => ele.stock)) // 700
    // (其实这个例子用sort方法就能实现,只是举个例子)
    
    
  • Math.min

    // e.g.1 取最小值
    // e.g.1 求数组最大值
    let data = [1,2,3,4,5,6,7,8]
    const big = Math.min(...data) // 1
    
    
  • Array.from

    // e.g.1 数组去重
    let data = [1,1,2,3,4,4,5,6]
    const arr = [...new Set(data)] // [1,2,3,4,5,6]
    
    
  • 字符串转数组

    // e.g.1 将一个字符串转成数组
    const arr = [...'hello'] // [‘h’, 'e', 'l', 'l', 'o']
    
    
  • 合并数组

    // e.g.1 合并两个数组
    let arr1 = [1,2,3,4,5,6]
    let arr2 = [1,2,3,4,5,6]
    let arr2 = [...arr1, ...arr2] // [1,2,3,4,5,6,1,2,3,4,5,6]
    
    
  • 合并对象

    let data1 = {
      name: '王二麻子',
      age: 12,
      class: '2(1)班'
    }
    let data2 = {
      name: '王二麻子',
      hobby: '王者荣耀'
    }
    
    let w2mz = {...data1, ...data2} 
    // 输出:
    {
      name: '王二麻子',
      age: 12,
      class: '2(1)班',
    	hobby: '王者荣耀'
    }
    
    // ** 注意: 当出现重复的key的时候,后面的key对应的val会覆盖掉前面的key对应的val
    
  • 充当函数省略参数 …other

    …other 在函数体内使用other的时候, other是一个由省略参数组成数组 e.g.1

const sum = (a, b, ...num) => {
    let total = num.reduce((prev, current) => current + prev, 0) 
    return a + b + total
}
sum(1, 2, 3, 4, 5, 6, 7, 8, 9)

e.g.2

// 实现一个累加器 要求 可以传任意个参数 函数返回一个所有参数的累加和
const sum = (...num) => num.reduce((prev, current) => current + prev, 0) 
console.log(sum(1, 2, 3, 4)) // 10

总结

有错别字或者理解有误的地方大佬们指出来哈。千万不要: he~ tui(我可以发语音😊)