一起来完成es5中新增的数组要领

媒介

一直以来想写一篇关于es5中新增数组的运用要领与源码完成的文章,拖了挺久了,趁着这夜深人静,大脑苏醒,又困意不在的时刻写下来。或许有人会问,现如今es6都大行其道了,还学es5是否是有些过期了,?,温故而知新,能够从中多学点嘛,而且我们是要自身完成这些要领,知其然还要知其所以然,不光要会用,还要晓得为何是如许用哒。

《一起来完成es5中新增的数组要领》

新增要领预览

es5中给js的数组增添了很多有用的要领,应用这些要领能够协助我们越发疾速轻易的写js代码,然后蛋疼的是低版本ie一定是不支撑的,所以………………自身着手饱食暖衣。让我们一步步看下如何运用与完成这些要领。

  1. forEach

  2. map

  3. filter

  4. some

  5. every

  6. indexOf

  7. lastIndexOf

  8. reduce

  9. reduceRight

forEach

这个要领作用是啥咧,就是轮回,遍历。比方平常我们在for轮回做如许的事的时刻以下。


var arr = [1, 2, 3, 4, 5, 6];

for (var i = 0, len = arr.length; i < len; i++) {
  console.log(arr[i], i, arr);
}

假如用forEach我们应当如何做呢?

var arr = [1, 2, 3, 4, 5, 6];

arr.forEach(function (e, i, array) {
  console.log(e, i, array)
})

是否是以为不必写for轮回了,霎时逼格都高了

forEach函数中的回调函数支撑三个参数,1、数组的值2、值的索引3、数组自身。如许的挪用体式格局是否是和jQuery中的$.each很像? 其实不然,jQuery和forEach回调函数的第一个和第二个参数恰好是反着来的。

看看对照

var arr = [1, 2, 3, 4, 5];

// forEach
arr.forEach(function (e, i, array) {
  console.log(e, i, array);
})

// output

1 0 [1, 2, 3, 4, 5]
2 1 [1, 2, 3, 4, 5]
3 2 [1, 2, 3, 4, 5]
4 3 [1, 2, 3, 4, 5]
5 4 [1, 2, 3, 4, 5]


// $.each
$.each(arr, function (i, e, array) { // 测试的时刻发明array是undefined,查了文档也发明没有第三个参数
  console.log(i, e, array);
})

// output

0 1 undefined
1 2 undefined
2 3 undefined
3 4 undefined
4 5 undefined

接着我们来看一下forEach的第二个参数,这个参数决议第一个回调函数的内部this指向


var arr = [1, 2, 3, 4, 5];

//  默许状况下,第二个参数不传入时
arr.forEach(function (e, i, array) {
  console.log(e, i, array, this);
})

// output
1 0 [1, 2, 3, 4, 5] window 
2 1 [1, 2, 3, 4, 5] window 
3 2 [1, 2, 3, 4, 5] window 
4 3 [1, 2, 3, 4, 5] window 
5 4 [1, 2, 3, 4, 5] window 

// 传入参数
arr.forEach(function (e, i, array) {
  console.log(e, i, array, this);
}, {name: 'qianlong'})

// output
1 0 [1, 2, 3, 4, 5] {name: 'qianlong'} 
2 1 [1, 2, 3, 4, 5] {name: 'qianlong'} 
3 2 [1, 2, 3, 4, 5] {name: 'qianlong'} 
4 3 [1, 2, 3, 4, 5] {name: 'qianlong'} 
5 4 [1, 2, 3, 4, 5] {name: 'qianlong'} 

末了接下来我们自身完成一下这个要领

var ObjPro = Object.prototype,
    hasOwn = ObjPro.hasOwnProperty,
    nativeArray = ObjPro.forEach;

Array.prototype.forEach = nativeArray || function (callBack, ctx) {  
  if (typeof callBack != 'function') return;
  
  for (var i =0, len = this.length; i < len; i++) {
    if (hasOwn.call(this, i)) {
      callBack.call(ctx, this[i], i, this);
    }
  }
}

map

map是干吗的! 其最主要的作用就是将原数组根据一定的划定规矩映射成一个新的数组。再将其返回,注重是返回一个新的数组,而不是将原数组直接转变运用体式格局和forEach相似,也是吸收一个回调函数,一个转变内部this指向的对象。

map

array.map(callback,[ thisObject])

callback

var arr = [1, 2, 3, 4, 5];

arr.map(function(value, index, array) {
  
});

举个栗子

var arr = [1, 2, 3, 4, 5];

var newArr = arr.map(function (e, i, array) {
  return 'hello ' +  e;
})

// output

["hello 1", "hello 2", "hello 3", "hello 4", "hello 5"] // newArr

[1, 2, 3, 4, 5] // arr

注重上面的return,假如我们不写return会如何呢?

var arr = [1, 2, 3, 4, 5];

var newArr = arr.map(function (e, i, array) {
  'hello ' +  e;
})

// output

[undefined, undefined, undefined, undefined, undefined] // newArr

[1, 2, 3, 4, 5] // arr

这一堆的undefined是啥状况,还记得一个函数实行完,假如没有显现的返回值,会返回什么吗? 没错 就是undefined,这就是缘由地点,等会经由历程源码,你就会越发邃晓。

末了我们自身完成一下map这个要领

var ObjPro = Object.prototype,
    hasOwn = ObjPro.hasOwnProperty,
    nativeMap = ObjPro.map;
    
Array.prototype.map = nativeMap || function (callBack, ctx) {
  if (typeof callBack != 'function') return;
  
  var returnArr = [];
  for(var i = 0, len = this.length; i < len; i++) {
    returnArr.push(callBack.call(ctx, this[i], i, this)); // 这就是为何回调函数没有返回值的状况下会获得一堆的undefined值,他将回调函数的返回值push到了一个数组内里,当你没有显现的返回值的时刻,天然push进去的就是undefined了     
  }
  return  returnArr;
}    

filter

接下来是filter,挑选,过滤的意义,给你一个数组,用一些你制订的前提,对个中的值举行过滤,末了获得你想要的新的数组。基础用法和map差不多

  
array.filter(callback,[ thisObject]);

然则和map也有差异的处所,filter须要你在callback处返回弱即是true 的值,才会将原数组中挑选出的值返回给你。

举个栗子


var arr = [0, 1, 2, 3, 4, 5];

var newArr = arr.filter(function (e, i, array) {
  return e;
})

// output

[1, 2, 3, 4, 5] // newArr

var newArr2 = arr.filter(function (e, i, array) {
  if (e >= 2) return true; 
})

// ouput
[2, 3, 4, 5] // newArr2

固然末了另有第二个参数转变内部this指向的参数可选,默许是window对象,你也能够传一个对象进去, 末了我们自身来完成一下这个api

var ObjPro = Object.prototype,
    hasOwn = ObjPro.hasOwnProperty,
    nativeFilter = ObjPro.filter;
    
Array.prototype.filter = nativeFilter || function (callBack, ctx) {
  if (typeof callBack != 'function') return;
  
  var returnArr = [];
  for(var i = 0, len = this.length; i < len; i++) {
    if (callBack.call(ctx, this[i], i, this)) {
      returnArr.push(this[i]);
    }
  }    
  return returnArr;
}

some vs every

some与接下里的every恰好相对,some是只需数组中的某个值,相符你给定的推断前提就返回true,而every则是数组中的一切值都相符你给定的推断前提的时刻才会返回true,不然就返回false,也就是说两个要领末了获得的都是true or false

举个栗子

    
var arr = [0, 1, 2, 3, 4, 5];

var result = arr.some(function (e, i, array) {
  if (e === 3) {return true};
});

// output      
true // result;

var arr = [0, 1, 2, 3, 4, 5];

var result2 = arr.every(function (e, i, array) {
  if (e > 3) {return true};
});
// output      
false // result;

some 和 every运用起来异常简朴,接下来我们自身完成一把


var ObjPro = Object.prototype,
    hasOwn = ObjPro.hasOwnProperty,
    nativeSome = ObjPro.some,
    nativeEvery = ObjPro.every;
    
// some    
Array.prototype.some = nativeSome || function (callBack, ctx) {
  if (typeof callBack != 'function') return;
  
  var resultValue = false;
  for(var i = 0, len = this.length; i < len; i++) {
    if (resultValue) {
      break;
    }
    resultValue = !!callBack.call(ctx, this[i], i, this); 
  }
  return  resultValue;
} 

// every

Array.prototype.every = nativeEvery || function (callBack, ctx) {
  if (typeof callBack != 'function') return;

  var resultValue = true;
  for (var i = 0, len = this.length; i < len; i++) {
    if (!resultValue) {
      break;    
    }
    resultValue = !!callBack.call(ctx, this[i], i, this);
  }    
  return resultValue;      
}   

indexOf

数组的indexOf要领和字符串的indexOf用法异常相似,array.indexOf(searchElement[, fromIndex]),针对给定的要查找的值,和最先查找的位置(可选),返回整数索引值。

举个例子


var arr = [0, 1, 2, 3, 4, 5];

arr.indexOf(1) // 1
arr.indexOf(3, 'qianlong') // 3 由于给定的最先索引值不能转化成数字,所以照样从0位置最先搜刮 
arr.indexOf(3, 4) // -1
arr.indexOf(3, '4') // -1
arr.indexOf('3') // -1 // 推断前提是强 3 !== '3' => -1

完成代码


var ObjPro = Object.prototype,
    hasOwn = ObjPro.hasOwnProperty,
    nativeIndexOf = ObjPro.indexOf;
    
Array.prototype.indexOf = nativeIndexOf || function (searchElement, fromIndex) {
  var returnIndex = -1,
      fromIndex = fromIndex * 1 || 0;
  for (var i = fromIndex, len = this.length; i < len; i++) {
    if (searchElement === this[i]) {
       returnIndex = i;
       break;
    }
  }             
  return returnIndex;        
}

lastIndexOf

数组的lastIndexOf要领和字符串的lastIndexOf用法异常相似,array. lastIndexOf(searchElement[, fromIndex]),针对给定的要查找的值,和最先查找的位置(可选),返回整数索引值。与indexOf差别的处所在于,它是从后往前查找。默许最先查找的位置是 array.length - 1

举个栗子

var arr = [0, 1, 2, 3, 4, 5, 4, 3, 2, 1, 0];

arr.lastIndexOf(1) // 9
arr.lastIndexOf(3, 'qianlong') // -1 这里和indexOf不一样,传入的值不能转化为数字将获得-1
arr.lastIndexOf(3, 4) // 3
arr.lastIndexOf(3, '4') // 3
arr.lastIndexOf('3') // -1 // 推断前提是强 3 !== '3' => -1

源码完成

var ObjPro = Object.prototype,
    hasOwn = ObjPro.hasOwnProperty,
    nativeLastIndexOf = ObjPro.lastIndexOf;
    
Array.prototype.lastIndexOf = nativeLastIndexOf || function (searchElement, fromIndex) {
  var len = this.length,
      returnIndex = -1,
      fromIndex = fromIndex * 1 || len - 1;
      
  for (var i = fromIndex; i > -1; i -= 1) {
    if (this[i] === searchElement){
      returnIndex = i;
      break;
    }
  }
  return returnIndex;
}

reduce

reduce 相对es5中数增加的其他要领都庞杂一些,我们能够经由历程栗子来看一下这个api怎样运用。起首基础参数以下

array.reduce(callback[, initialValue]),吸收一个回调函数,一个初始化的值initialValue 。个中callback参数分别是初始化的值initialValue ,假如没有传入initialValue,则默许是数组的第一项。第二个及其背面的参数分别是当前值,索引,数组自身

var arr = [0, 1, 2, 3, 4, 5],
    sum = arr.reduce(function (init, cur, i, array) {
      return init + cur;
    });    
    
   //output
   sum // 15
   

我们来看一下上面的实行历程是如何的。

第一回合

// 由于initialValue没有传入所以回调函数的第一个参数为数组的第一项

init = 0;
cur = 1;

=> init + cur = 1;

第二回合

init = 1;
cur = 2;

=> init + cur = 3;

第三回合

init = 3;
cur = 3;

=> init + cur = 6;

第四回合

init = 6;
cur = 4;

=> init + cur = 10;

第五回合

init = 10;
cur = 5;

=> init + cur = 15;

末了获得效果15

那末我们如何自身完成一个reduce呢?

var ObjPro = Object.prototype,
    hasOwn = ObjPro.hasOwnProperty,
    nativeReduce = ObjPro.reduce;
    
Array.prototype.reduce = nativeReduce || function (callBack, initialVal) {
  if (typeof callBack != 'function') return;
  
  var init = initialVal,
      i = 0;
  
      if (init === void (0)) {
        init = this[0];
        i = 1;
      }
  for (i, len = this.length; i < len; i++) {
    if (hasOwn.call(this, i)) {
      init = callBack(init, this[i], i, this);
    }  
  }
  return init;    
}   
    

reduceRight

reduceRight基础用法与reduce相似,比如indexOf与lastIndexOf,差别之处在于它是从最右侧的值最先盘算的。我们直接去看源码怎样完成吧

var ObjPro = Object.prototype,
    hasOwn = ObjPro.hasOwnProperty,
    nativeReduceRight = ObjPro.reduceRight;
   
Array.prototype.reduceRight = nativeReduceRight || function (callBack, initialVal) {
  if (typeof callBack != 'function') return;
  
  var init = initialVal,
      len = this.length,
      i = len - 1;
      
  if (init === void(0)) {
    init = this[len - 1];
    i -= 1;
  }
  for (i; i > -1; i -=1) {
    if (hasOwn.call(this, i)) {
      init = callBack(init, this[i], i, this);
    }
  }    
  return init;
}     

末端

终究写完了,断断续续快写了两天,迎接人人看了今后提一些看法,函数完成的不一定都对,一定有一些问题的处所,迎接人人斧正。

末了把代码放到github上面了

github地点

列位大大,请让我打个小广告。???

博客地点

    原文作者:谦龙
    原文地址: https://segmentfault.com/a/1190000007254447
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞