# forEach 原理

# 使用 for 实现

const array = ['稚名真白', '樱岛麻衣', '蝶祈']
Array.prototype._forEach = function (callback) {
  for (let i = 0; i < this.length; i++){
    callback(this[i], i, this)
  }
}
array._forEach((value, index, array) => {
  console.log(value, index, array)
})
/*
 稚名真白 0 [' 稚名真白 ', ' 樱岛麻衣 ', ' 蝶祈 ']
 樱岛麻衣 1 [ ' 稚名真白 ', ' 樱岛麻衣 ', ' 蝶祈 ' ]
 蝶祈 2 [ ' 稚名真白 ', ' 樱岛麻衣 ', ' 蝶祈 ' ]
*/

# 使用 for in 实现

const array = ['稚名真白', '樱岛麻衣', '蝶祈']
Array.prototype._forEach = function (callback) {
  for (let key in this) {
    if ('NaN' === (+key + '')) return
    callback(this[key], key, this)
  }
}
array._forEach((value, index, array) => {
  console.log(value, index, array)
})
/*
 稚名真白 0 [' 稚名真白 ', ' 樱岛麻衣 ', ' 蝶祈 ']
 樱岛麻衣 1 [ ' 稚名真白 ', ' 樱岛麻衣 ', ' 蝶祈 ' ]
 蝶祈 2 [ ' 稚名真白 ', ' 樱岛麻衣 ', ' 蝶祈 ' ]
*/

# filter 原理

# 使用 for 实现

const array = ['稚名真白', '樱岛麻衣', '蝶祈']
Array.prototype._filter = function (callback) {
  const res = []
  for (let i = 0; i < this.length; i++){
    callback(this[i], i, this) && res.push(this[i])
  }
  return res
}
const ゆずりはいのり = array._filter((value, index, array) => {
  return value === '蝶祈'
})
console.log(ゆずりはいのり) // [' 蝶祈 ']

# 使用 for in 实现

const array = ['稚名真白', '樱岛麻衣', '蝶祈']
Array.prototype._filter = function (callback) {
  const res = []
  for (const key in this) {
    if ('NaN' === (+key + '')) return res
    callback(this[key], key, this) && res.push(this[key])
  }
}
const ゆずりはいのり = array._filter((value, index, array) => {
  return value === '蝶祈'
})
console.log(ゆずりはいのり) // [' 蝶祈 ']

# map 原理

# 使用 for 实现

const array = ['稚名真白', '樱岛麻衣', '蝶祈']
Array.prototype._map = function (callback) {
  const res = []
  for (let i = 0; i < this.length; i++){
    res.push(callback(this[i], i, this))
  }
  return res
}
const newArray = array._map((value, index, array) => {
  return index + '-' + value
})
console.log(newArray) // ['0 - 稚名真白 ', '1 - 樱岛麻衣 ', '2 - 蝶祈 ']

# 使用 for in 实现

const array = ['稚名真白', '樱岛麻衣', '蝶祈']
Array.prototype._map = function (callback) {
  const res = []
  for (const key in this) {
    if ('NaN' === (+key + '')) return res
    res.push(callback(this[key], key, this))
  }
}
const newArray = array._map((value, index, array) => {
  return index + '-' + value
})
console.log(newArray) // ['0 - 稚名真白 ', '1 - 樱岛麻衣 ', '2 - 蝶祈 ']

# reduce

# 使用 for 实现

const array = [2, 4, 6, 7, 8]
Array.prototype._reduce = function (callback, initValue) {
  if (Object.prototype.toString.call(callback) !== '[object Function]') {
    throw new Error('callback must be function')
  }
  // 判断是否传了初始值,没有传就从下标 1 开始遍历,否则从下标 0 开始遍历
  let initIndex = arguments.length == 1 ? 1 : 0; 
  // 判断初始值,如果没传就默认取下标 0 的元素,否则取传过来的初始值为默认值
  let accumulator = initIndex ? this[0] : initValue
  for (let i = initIndex; i < this.length; i++) accumulator = callback(accumulator, this[i], i, this)
  return accumulator  
}
const res = array._reduce((accumulator, currentValue, currentIndex,  array) => {
  console.log(accumulator) // 10 14 30 66 115
  return accumulator += currentValue ** 2 // (10 + 2**2) (14 + 4**4) (30 + 6**6) (66 + 7**7) (115 + 8**8)
}, 10)
console.log(res) // 179

# 使用 for in 实现

const array = [2, 4, 6, 7, 8]
Array.prototype._reduce = function (callback, initValue) {
  if (Object.prototype.toString.call(callback) !== '[object Function]') {
    throw new Error('callback must be function')
  }
  // 判断是否传了初始值,没有传就从下标 1 开始遍历,否则从下标 0 开始遍历
  let initIndex = arguments.length === 1 ? 1 : 0; 
  // 判断初始值,如果没传就默认取下标 0 的元素,否则取传过来的初始值为默认值
  let accumulator = initIndex ? this[0] : initValue
  for (const key in this) {
    if('NaN' === +key + '') return accumulator
    accumulator = callback(accumulator, this[key], key, this)
  }
}
const res = array._reduce((accumulator, currentValue, currentIndex,  array) => {
  console.log(accumulator) // 10 14 30 66 115
  return accumulator += currentValue ** 2 // 执行流程 -> (10 + 2**2) (14 + 4**4) (30 + 6**6) (66 + 7**7) (115 + 8**8)
}, 10)
console.log(res) // 179