深入理解数组内置方法

数组的方法大概分es3、es5、es6版本了,各个版本都有一些新的定义。
鉴于es5 已经成为当前主流标准,所以不区分es3 和es5了,直接区分es5和es6。

es5数组内置方法:
1,Array.prototype.push(itemX, itemY) ---向数组的末尾添加一个或更多元素,并返回新的长度。
2,Array.prototype.pop() --删除并返回数组的最后一个元素。
3,Array.prototype.unshift(itemX, itemY) -- 向数组的开头添加一个或更多元素,并返回新的长度。
4,Array.prototype.shift() -- 删除并返回数组的第一个元素。
5,Array.prototype.concat(arrayX,arrayX,......,arrayX) --连接两个或更多的数组,并返回结果,把后面的数组追加到第一个数组。
6,Array.prototype.join(指定分隔符) -- 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
6.1,String.prototype.split(指定分隔符) -- 把字符串通过指定分隔符形成数组
7,Array.prototype.reverse() -- 颠倒数组中元素的顺序。
8,Array.prototype.sort(sortby) --对数组的元素进行排序
8,Array.prototype.slice(start, end) --从某个已有的数组返回选定的元素
9,Array.prototype.splice(index,howmany,item1,.....,itemX) --删除元素,并向数组添加新元素。
10,Array.prototype.toString() --把数组转换为字符串,并返回结果。
11,Array.prototype.toLocaleString() --把数组中每一元素转换为本地字符串,再拼接,返回结果,主要是时间类。
12,Array.prototype.valueOf --返回数组对象的原始值,内部用,其实就是返回它自己
13,Array.prototype.toSource --返回该对象的源代码。// 大部分不支持

新增方法(存在ie6-ie8不兼容问题):

14,Array.prototype.forEach() --是Array新方法中最基本的一个,就是遍历,循环
15,Array.prototype.map() --原数组被“映射”成对应新数组
16,Array.prototype.filter() -- 根据过滤条件对原数组进行过滤,形成新数组
17,Array.prototype.some() --是否“某些项”合乎条件 返回true/false
18,Array.prototype.every() --是否都符合条件 返回true/false
19,Array.prototype.indexOf() --包含指定元素的第一个位置
20,Array.prototype.lastIndexOf() --从数组后面找到该元素的第一个位置
21,Array.prototype.reduce() --迭代”、“递归(recursion), 返回一个回调函数结果
22,Array.prototype.reduceRight() --从数组的末端开始迭代”、“递归(recursion), 返回一个回调函数结果

改变数组的方法有以下

push
pop
unshift
shift
splice
reverse
sort

重点讲几个方法,存在混淆点

 // push 可以向尾部添加1个或者多个
var arr = [1, 2, 3];
arr.push(4, 5) // arr = [1, 2, 3, 4, 5] 以前都是插入单个,还未插入多个
// unshift 可以向头部添加1个或者多个
arr.unshift(4, 5) // arr = [4, 5, 1, 2, 3, 4, 5]
//concat 并不会改变数组
var arr2 = [10, 11];
var arr3 = arr.concat(arr2) // arr 和 arr2并不会发生变化
//sort(sortby) sortby 是一个函数,返回值为大于0 小于0 等于0
sortby = function(a, b){
  return a-b;
 //a -b > 0   a排在b后面
 // a-b = 0 不换位置
 // a-b < 0 a在b前面
}
// slice(start, end) start,end 说明
/**
start 必选 ,end可选
*/
var arr = [1, 2, 3, 4];
//start 取值情况
var arr4 = arr.slice(0, 1) //   arr4 = 1  从0开始,截取1位
var arr4 = arr.slice(1, 1) //   arr4 = 2  从1开始,截取1位
var arr4 = arr.slice(-1, 1) //   arr4 = 4  从倒数第一位开始,截取1位
var arr4 = arr.slice(5, 1) //   arr4 = []  超出数组长度,返回空数组
// end 取值情况
var arr4 = arr.slice(1) //   arr4 = [2, 3, 4]  end为空,从第一位开始,截取剩下的元素
var arr4 = arr.slice(1, 0) // arr4 = [] ,截取0个元素时,返回空数组
var arr4 = arr.slice(1,10) //arr4 = [2, 3, 4]  end超出数组长度时,截取剩下的元素
var arr4 = arr.slice(1, -1) //arr4 = [2, 3] end为负数时,截取到数组长度+负数的位置,不包含该位置
var arr4 = arr.slice(-1, -1) // arr4 = [] start end 均为负数时,以start为开始,若end在start前返回空,在start后,获取剩下元素

//splice(index,howmany,item1,.....,itemX)
/**
index: 起始位
howmany: 多少个
item1...itemx:插入值
*/
var arr = [1, 2, 3, 4];
arr.splice(0) // arr = [] 为一个或两个参数时,是删除操作
arr.splice(1) // arr = [2, 3, 4]
arr.splice(-1) // arr = [1, 2, 3] 当index为负值时,则从length+index位开始计算
arr.splice(-2, 1) // arr = [1, 2, 4] 
arr.splice(1, 0) //arr = [1, 2, 3 ,4] 为0时不删除
arr.splice(1, 5) // arr = [1] 超出长度,以最大长度计算
arr.splice(1, 1, 10) // arr = [1,10, 3, 4] 先删除,然后在指定位置插入值
arr.splice(1, 1, 10,20) // arr = [1,10,20, 3, 4]  有多个则依次插入多个
arr.splice(10, 1, 555) // arr = [1, 2, 3, 4, 555] 起始值超出长度时,则在最后面插入

es6的方法演示及兼容写法

  1. forEach(callback,[ thisObject])
    callback回调函数 = function (item, index ,array)
    thisObject 一个可选的上下文参数(改变回调函数里面的this指向)
  var data = {
  users: ['张含韵', '李小璐', '白百何'],
  sendEmails: function(user){
    if(this.isValidUser(user)){
      console.log('你好' + user);
    } else {
      console.log('你好不是本家人')
    }
  },
  isValidUser: function(user){
    return /^张/.test(user)
  }
}
data.users.forEach(data.sendEmails, data)
 //此时,如果不带data,会报错的,执行sendEmails方法用到this.isValidUser方法,此时this指向window,带了data,指向data
//jquery中也有each方法。容易混淆
$.each([], function(index, item, array) {
    // ...
});
//回调函数中的参数 第一位和第二位与数组中的顺序恰恰相反,使用的时候要注意一下
// 兼容IE6-8
if(typeof Array.prototype.forEach !== 'function'){
  Array.prototype.forEach = function(fn, context){
    for(var k = 0, len = this.length; k < len; k++){
      if(typeof fn === 'function' && Object.prototype.hasOwnProperty.call(this, k)){
        fn.call(context, this[k], k, this)
      }
    }
  }
}
//this指向的是调用的数组
  1. array.map(callback,[ thisObject]); //返回新数组
[].map(function(value, index, array) {
    // ...
});
var arr = [1, 2, 3];
var arr2 = arr.map(function(value, index, array){
   return value  * 2 // 必须要return 否者返回 undefined
})
// arr2  = [2, 4, 6]
// 兼容IE6-8
if(typeof Array.prototype.map != 'function'){
  Array.prototype.map = function(fn, context) {
    var arr = [];
    if(typeof fn === 'function' ){
      for(var k = 0, len = this.length; k < len; k++){
          arr.push(fn.call(context, this[k], k, this))
      }
    }
    return arr;
  }
}

3.array.filter(callback,[ thisObject]); //返回符合条件的新数组
if(typeof Array.prototype.map != 'function'){
Array.prototype.map = function(fn, context) {
var arr = [];
if(typeof fn === 'function' ){
for(var k = 0, len = this.length; k < len; k++){
fn.call(context, this[k], k, this) && arr.push(this[k]) //fn返回为真 则插入该值
}
}
return arr;
}
}

  1. array.some(callback,[ thisObject]); // 其中某项符合, 返回true/false
  var arr = [1, 4, 8];
  var result = arr.some(function(item, index ,array){
      if(item > 4){
        return true;
      }
  })
  result === true
// 兼容IE6-8
if(typeof Array.prototype.some!= 'function'){
  Array.prototype.some = function(fn, context) {
    var passed = false;
    if(typeof fn === 'function'){
      for(var k = 0, len = this.length; k < len; k++){
        if(passed === true) {
          break;
        } 
        passed = !!fn(context, this[k], k, this);
      }
    }
return passed
  }
}
  1. every(callback,[ thisObject]); //全部符合,返回true/false
   var arr = [1, 4, 8];
  var result = arr.every(function(item, index ,array){
      if(item > 4){
        return true;
      }
  })
  result === false
// 兼容IE6-8
if(typeof Array.prototype.every!= 'function'){
  Array.prototype.every= function(fn, context) {
    var passed = true;
    if(typeof fn === 'function'){
      for(var k = 0, len = this.length; k < len; k++){
        if(passed === false) {
          break;
        } 
        passed = !!fn(context, this[k], k, this);
      }
    }
    return passed
  }
}
  1. array.indexOf(searchElement[, fromIndex])
    indexOf方法在字符串中自古就有,string.indexOf(searchString, position)。数组这里的indexOf方法与之类似。
    返回整数索引值,如果没有匹配(严格匹配),返回-1. fromIndex可选,表示从这个位置开始搜索,若缺省或格式不合要求,使用默认值0,我在FireFox下测试,发现使用字符串数值也是可以的,例如"3"和3都可以。
var data = [2, 5, 7, 3, 5];

console.log(data.indexOf(5, "x")); // 1 ("x"被忽略)
console.log(data.indexOf(5, "3")); // 4 (从3号位开始搜索)

console.log(data.indexOf(4)); // -1 (未找到)
console.log(data.indexOf("5")); // -1 (未找到,因为5 !== "5")
// 兼容IE6-8
if (typeof Array.prototype.indexOf != "function") {
  Array.prototype.indexOf = function (searchElement, fromIndex) {
    var index = -1;
    fromIndex = fromIndex * 1 || 0;

    for (var k = 0, length = this.length; k < length; k++) {
      if (k >= fromIndex && this[k] === searchElement) { //大于起始位且相等
          index = k;
          break;
      }
    }
    return index;
  };
}
  1. array.lastIndexOf(searchElement[, fromIndex])
    lastIndexOf方法与indexOf方法类似:只是lastIndexOf是从字符串的末尾开始查找,而不是从开头。还有一个不同就是fromIndex的默认值是array.length - 1而不是0.
if (typeof Array.prototype.lastIndexOf != "function") {
  Array.prototype.lastIndexOf = function (searchElement, fromIndex) {
    var index = -1, length = this.length;
    fromIndex = fromIndex * 1 || length - 1;

    for (var k = length - 1; k > -1; k-=1) {
        if (k <= fromIndex && this[k] === searchElement) {
            index = k;
            break;
        }
    }
    return index;
  };
}
var data = [2, 5, 7, 3, 5];

console.log(data.lastIndexOf(5)); // 4
console.log(data.lastIndexOf(5, 3)); // 1 (从后往前,索引值小于3的开始搜索)

console.log(data.lastIndexOf(4)); // -1 (未找到)
  1. array.reduce(callback[, initialValue])
    callback函数接受4个参数:之前值、当前值、索引值以及数组本身。initialValue参数可选,表示初始值。若指定,则当作最初使用的previous值;如果缺省,则使用数组的第一个元素作为previous初始值,同时current往后排一位,相比有initialValue值少一次迭代。
var sum = [1, 2, 3, 4].reduce(function (previous, current, index, array) {
  return previous + current;
});

console.log(sum); // 10

说明:

因为initialValue不存在,因此一开始的previous值等于数组的第一个元素。
从而current值在第一次调用的时候就是2.
最后两个参数为索引值index以及数组本身array.
执行过程:
// 初始设置
previous = initialValue = 1, current = 2

// 第一次迭代
previous = (1 + 2) = 3, current = 3

// 第二次迭代
previous = (3 + 3) = 6, current = 4

// 第三次迭代
previous = (6 + 4) = 10, current = undefined (退出)

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

// 二维数组扁平化
var flatten = matrix.reduce(function (previous, current) {
  return previous.concat(current);
});

console.log(flatten); // [1, 2, 3, 4, 5, 6]
// 兼容ie6-8
if (typeof Array.prototype.reduce != "function") {
  Array.prototype.reduce = function (callback, initialValue ) {
     var previous = initialValue, k = 0, length = this.length;
     if (typeof initialValue === "undefined") {
        previous = this[0];
        k = 1;
     }
     
    if (typeof callback === "function") {
      for (k; k < length; k++) {
         this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
      }
    }
    return previous;
  };
}
  1. array.reduceRight(callback[, initialValue])
    reduceRight是从数组的末尾开始实现
var data = [1, 2, 3, 4];
var specialDiff = data.reduceRight(function (previous, current, index) {
  if (index == 0) {
    return previous + current;
  }
  return previous - current;
});

console.log(specialDiff); // 0

// 初始设置
index = 3, previous = initialValue = 4, current = 3

// 第一次迭代
index = 2, previous = (4- 3) = 1, current = 2

// 第二次迭代
index = 1, previous = (1 - 2) = -1, current = 1

// 第三次迭代
index = 0, previous = (-1 + 1) = 0, current = undefined (退出)

if (typeof Array.prototype.reduceRight != "function") {
  Array.prototype.reduceRight = function (callback, initialValue ) {
    var length = this.length, k = length - 1, previous = initialValue;
    if (typeof initialValue === "undefined") {
        previous = this[length - 1];
        k--;
    }
    if (typeof callback === "function") {
       for (k; k > -1; k-=1) {          
          this.hasOwnProperty(k) && (previous = callback(previous, this[k], k, this));
       }
    }
    return previous;
  };
}

应用场景举例:
var eleDivs = document.getElementsByTagName("div");
Array.prototype.forEach.call(eleDivs, function(div) {
console.log("该div类名是:" + (div.className || "空"));
});

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容