JS Array迭代的源码思想

一文搞懂JS Array迭代原理

//【问题引入1】两个变量,两个函数,两两配对通过for循环进行操作,返回经过处理后等长的数组,会出现代码冗余的情况
function oodlify(s) {
  return s.replace(/[aeiou]/g, 'oodle');
}
function izzlify(s) {
  return s.replace(/[aeiou]+/g, 'izzle');
}
const fellowship = [
  'frodo',
  'sam',
  'gandalf',
  'aragorn',
  'boromir',
  'legolas',
  'gimli',
];
const band = [
  'John',
  'Paul',
  'George',
  'Ringo',
];

function oodlifyArray(input) {
  let output = [];
  for (let item of input) {
      let newItem = oodlify(item);
      output.push(newItem);
  }
  return output;
}

function izzlifyArray(input) {
  let output = [];
  for (let item of input) {
      let newItem = izzlify(item);
      output.push(newItem);
  }
  return output;
}

let bandoodle = oodlifyArray(band);
let bandizzle = izzlifyArray(band);
let fellowshipoodle = oodlifyArray(fellowship);
let fellowshipizzle = izzlifyArray(fellowship);


//因此可以抽象出一个通过的模式,给定一个函数和一个数组,通过这个函数,把数组中每一个元素做操作后放到新的数组里。
//注意:map 并没有覆盖到每一种可能需要用到的循环。只有当你想创建一个和输入数组同样长度的数组时才有用。
function map_for(f,a){
  let output=[]
  for(let item of a){
    output.push(f(item))
  }
  return output
}
function map_recursion(f,a){
  if(a.length ===0){return [];}
  return [f(a[0]).concat(map(f,a.slice(1)))]
}

//【问题引入2】如果你想要向数组中增加几个元素呢?或者想找一个列表中的最短字符串是哪个?其实有时我们对数组进行处理,最终只想得到一个值而已。
const heroes1 = [
  {name: 'Hulk', strength: 90000},
  {name: 'Spider-Man', strength: 25000},
  {name: 'Hawk Eye', strength: 136},
  {name: 'Thor', strength: 100000},
  {name: 'Black Widow', strength: 136},
  {name: 'Vision', strength: 5000},
  {name: 'Scarlet Witch', strength: 60},
  {name: 'Mystique', strength: 120},
  {name: 'Namora', strength: 75000},
];


//找到最强壮的
let strongest = {strength: 0};
for (hero of heroes1) {
    if (hero.strength > strongest.strength) {
        strongest = hero;
    }
}
//保存所有英雄的总能量
let combinedStrength = 0;
for (hero of heroes1) {
    combinedStrength += hero.strength;
}

//两个的功能都是对数组进行处理,最终得到一个值。所以,我们创建一个 reduce 函数来封装这个模式。
//注意:没有人说 reduce 方法只能返回基本类型,它可以是一个 object 类型,甚至可以是另一个数组
function reduce(f,initialVal,a){
  let working=initialVal;
  for(let item of a ){
    working=f(working,item);
  }
  return working;
}

//【问题引入3】现在我们有了 map 处理数组中的每个元素,有了 reduce 可以处理数组最终得到一个值。但是如果想获取数组中的某些元素该怎么办?
const heroes2 = [
  {name: 'Hulk', strength: 90000, sex: 'm'},
  {name: 'Spider-Man', strength: 25000, sex: 'm'},
  {name: 'Hawk Eye', strength: 136, sex: 'm'},
  {name: 'Thor', strength: 100000, sex: 'm'},
  {name: 'Black Widow', strength: 136, sex: 'f'},
  {name: 'Vision', strength: 5000, sex: 'm'},
  {name: 'Scarlet Witch', strength: 60, sex: 'f'},
  {name: 'Mystique', strength: 120, sex: 'f'},
  {name: 'Namora', strength: 75000, sex: 'f'},
];
// //找到所有的女性英雄
// let femaleHeroes = [];
// for (let hero of heroes2) {
//     if (hero.sex === 'f') {
//         femaleHeroes.push(hero);
//     }
// }
// //找到所有能量大于500的英雄
// let superhumans = [];
// for (let hero of heroes2) {
//     if (hero.strength >= 500) {
//         superhumans.push(hero);
//     }
// }

//逻辑严密,看起来还不错?但是里面又出现了重复的情况。实际上,区别在于 if 的判断语句,那么能不能把 if 语句重构到一个函数中呢?
//断言函数predicate(只返回true和false的函数)
function isFemaleHero(hero) {
  return (hero.sex === 'f');
}
function isSuperhuman(hero) {
  return (hero.strength >= 500);
}
let femaleHeroes = [];
for (let hero of heroes2) {
  if (isFemaleHero(hero)) {
      femaleHeroes.push(hero);
  }
}
let superhumans = [];
for (let hero of heroes2) {
  if (isSuperhuman(hero)) {
      superhumans.push(hero);
  }
}

//两个的功能都是对数组进行处理,最终得到一个值其子数组。所以,我们创建一个 filter函数来封装这个模式。
function filter(predicate,a){
  let working=[]
  for(let item of a ){
    if(predicate(item)){
      working=working.concat(item)
    }
  }
}


//【问题引入4】只想返回一个英雄。
//用filter就可以这样
const blackWidow=heroes2.filter((item)=>{
  return item.name == 'Black Widow'
})
console.log(blackWidow)

//存在一个问题,效率太低,如果找到了还会继续匹配后面的元素,因此,依旧利用断言函数,我们写一个 find 函数来返回第一次匹配上的元素。
function find(predicate,a){
  for(let item of a ){
    if(predicate(item)){
      return item
    }
  }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值