JavaScript数组常用方法整理

整理一下常用的数组方法(含ES6)

Array.from(arrayLike[, mapFn[, thisArg]])

将一个类数组对象或可遍历对象转换成真正的数组, 然后就可以在该对象上使用数组方法

该方法有一个可选参数mapFn,让你可以在最后生成的数组上再执行一次 map 方法后再返回。也就是说 Array.from(obj, mapFn, thisArg) 就相当于 Array.from(obj).map(mapFn, thisArg)

例子:

Array.from('abc');  // ['a', 'b', 'c']

var a = Array.from(document.querySelectorAll('p'))
Array.isArray(a) // true

(function () {
    var args = Array.from(arguments);
    return args;
})(1, 2, 3);

// ES6
(function(first, ...rest) {
    console.log('first: ', first);
    console.log('rest: ', rest);
})(1, 2, 3);
// ES5
(function() {
    var first = arguments[0];
    var rest = Array.from(arguments).slice(1);
    console.log('first: ', first);
    console.log('rest: ', rest);
})(1, 2, 3);
// 输出
// first:  1
// rest:  [ 2, 3 ]

Array.from([1, 2, 3], x => x + x); // [2, 4, 6]

Array.isArray()

判断某个值是否为Array
. 如果是,则返回 true, 否则返回 false

例子:

Array.isArray(new Array()); // true
// 鲜为人知的事实:其实 Array.prototype 也是一个数组。
Array.isArray(Array.prototype); // true

Polyfill:

if(!Array.isArray){
    Array.isArray = function(arg){
        return Object.prototype.toString.call(arg) === '[object Array]';
    };
}

Array.prototype.concat()

将传入的数组或非数组值与原数组合并,组成一个新的数组并返回(不改变原数组)

let a1 = [1,2];
let a2 = [3,4];
let a3 = [5,6];
a1.concat(a2); // [1, 2, 3, 4]

a1.concat(3,4,5); // [1, 2, 3, 4, 5]

a1.concat(a2, a3); // [1, 2, 3, 4, 5, 6]

Array.prototype.copyWithin(target, start, end)

copyWithin() 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,而不修改其大小.

例子:

/*
 * target: 0 为基底的索引,复制序列到该位置。如果是负数,target 将从末尾开始计算
 * start: 0 为基底的索引,开始复制元素的起始位置. 如果 start 被忽略,copyWithin 将会从0开始复制
 * end: 0 为基底的索引,开始复制元素的结束位置. 如果 end 被忽略,copyWithin 将会复制到 arr.length
*/

['alpha', 'bravo', 'charlie', 'delta'].copyWithin(2, 0);
// results in ["alpha", "bravo", "alpha", "bravo"]

[].copyWithin.call({length: 5, 3: 1}, 0, 3);
// { 0: 1, 3: 1, length: 5 }
// https://segmentfault.com/q/1010000004571952

Polyfill:

if (!Array.prototype.copyWithin) {
  Array.prototype.copyWithin = function(target, start/*, end*/) {
    // Steps 1-2.
    if (this == null) {
      throw new TypeError('this is null or not defined');
    }

    var O = Object(this);

    // Steps 3-5.
    var len = O.length >>> 0;

    // Steps 6-8.
    var relativeTarget = target >> 0;

    var to = relativeTarget < 0 ?
      Math.max(len + relativeTarget, 0) :
      Math.min(relativeTarget, len);

    // Steps 9-11.
    var relativeStart = start >> 0;

    var from = relativeStart < 0 ?
      Math.max(len + relativeStart, 0) :
      Math.min(relativeStart, len);

    // Steps 12-14.
    var end = arguments[2];
    var relativeEnd = end === undefined ? len : end >> 0;

    var final = relativeEnd < 0 ?
      Math.max(len + relativeEnd, 0) :
      Math.min(relativeEnd, len);

    // Step 15.
    var count = Math.min(final - from, len - to);

    // Steps 16-17.
    var direction = 1;

    if (from < to && to < (from + count)) {
      direction = -1;
      from += count - 1;
      to += count - 1;
    }

    // Step 18.
    while (count > 0) {
      if (from in O) {
        O[to] = O[from];
      } else {
        delete O[to];
      }

      from += direction;
      to += direction;
      count--;
    }

    // Step 19.
    return O;
  };
}

Array.prototype.every(callback[, thisArg])

测试数组的所有元素是否都通过了指定函数的测试(每一项都通过才返回true)

例子:

// 检测数组中的所有元素是否都大于 10

// callback被调用时传入三个参数:元素值,元素的索引,原数组
function isBigEnough(element, index, array) {
  return (element.value >= 10);
}
var a = [{ value: 12, id: 1 }, { value: 11, id: 2 }]
var b = [{ value: 8, id: 1 }, { value: 11, id: 2 }]
// apassed is true
var apassed = a.every(isBigEnough);
// bpassed is false
var bpassed = b.every(isBigEnough);

Polyfill:

if (!Array.prototype.every)
{
  Array.prototype.every = function(fun /*, thisArg */)
  {
    'use strict';

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== 'function')
        throw new TypeError();

    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++)
    {
      if (i in t && !fun.call(thisArg, t[i], i, t))
        return false;
    }

    return true;
  };
}

** Array.prototype.some()**

测试数组中的某些元素是否通过了指定函数的测试(有一个符合条件的元素立即返回true), 用法同every()

以上两种方法区别

every() 每一项都返回true才返回true
some() 只要有一项返回true就返回true

Array.prototype.filter(callback[, thisArg])

用指定的函数测试所有元素,并创建一个包含所有通过测试的元素的新数组(筛选出所有满足条件的)

例子:
下例使用 filter 创建了一个新数组,该数组的元素由原数组中值大于 10 的元素组成

function isBigEnough(element, index, array) {
  return element >= 10;
}
// filtered is [12, 130, 44]
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);

Polyfill:

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisArg */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
      throw new TypeError();

    var res = [];
    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++)
    {
      if (i in t)
      {
        var val = t[i];

        // NOTE: Technically this should Object.defineProperty at
        //       the next index, as push can be affected by
        //       properties on Object.prototype and Array.prototype.
        //       But that method's new, and collisions should be
        //       rare, so use the more-compatible alternative.
        if (fun.call(thisArg, val, i, t))
          res.push(val);
      }
    }

    return res;
  };
}

注意:filter()和every(),some()用法相同,返回值不同,filter返回一个新数组

Array.prototype.includes()

includes() 方法用来判断一个数组是否包含一个指定的值,如果是,酌情返回 true或 false

例子:

let a = [{a: 1}, 2, 3];
a.includes(2);  // true
a.includes({a: 1}); //false

Polyfill:

// https://tc39.github.io/ecma262/#sec-array.prototype.includes
if (!Array.prototype.includes) {
  Object.defineProperty(Array.prototype, 'includes', {
    value: function(searchElement, fromIndex) {

      // 1. Let O be ? ToObject(this value).
      if (this == null) {
        throw new TypeError('"this" is null or not defined');
      }

      var o = Object(this);

      // 2. Let len be ? ToLength(? Get(O, "length")).
      var len = o.length >>> 0;

      // 3. If len is 0, return false.
      if (len === 0) {
        return false;
      }

      // 4. Let n be ? ToInteger(fromIndex).
      //    (If fromIndex is undefined, this step produces the value 0.)
      var n = fromIndex | 0;

      // 5. If n ≥ 0, then
      //  a. Let k be n.
      // 6. Else n < 0,
      //  a. Let k be len + n.
      //  b. If k < 0, let k be 0.
      var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);

      // 7. Repeat, while k < len
      while (k < len) {
        // a. Let elementK be the result of ? Get(O, ! ToString(k)).
        // b. If SameValueZero(searchElement, elementK) is true, return true.
        // c. Increase k by 1.
        // NOTE: === provides the correct "SameValueZero" comparison needed here.
        if (o[k] === searchElement) {
          return true;
        }
        k++;
      }

      // 8. Return false
      return false;
    }
  });
}

Array.prototype.find()

数组中某个元素满足测试条件,find方法对数组中的每一项元素执行一次callback函数,直至有一个callback返回true.当找到了这样一个元素后,该方法会立即返回这个元素的值,否则返回undefined(找到一个满足条件的即返回该元素)

这个方法返回第一个符合条件元素的值, 用法和上面类似

例子:用对象的属性查找数组里的对象


var inventory = [
    {name: 'apples', quantity: 2},
    {name: 'bananas', quantity: 0},
    {name: 'cherries', quantity: 5}
];

function findCherries(fruit) { 
    return fruit.name === 'cherries';
}
// { name: 'cherries', quantity: 5 }
console.log(inventory.find(findCherries)); 

Array.prototype.findIndex()

用来查找数组中某指定元素的索引, 如果找不到指定的元素, 则返回 -1

区别find()方法:findIndex()
方法返回的是满足条件的元素的索引,而非它的值

Array.prototype.forEach()

forEach()方法让数组的每一项都执行一次给定的函数,forEach函数不支持break,不能跳出循环

例子:
从每个数组中的元素值中更新一个对象中每个属性的值

function Counter() {
  this.sum = 0;
  this.count = 0;
}
Counter.prototype.add = function(array) {
  array.forEach(function(entry) {
    this.sum += entry;
    ++this.count;
  }, this);
  // ^---- Note
};

var obj = new Counter();
obj.add([2, 5, 9]);
// 3 
obj.count
// 16
obj.sum

对象复制函数


function copy(obj) {
  var copy = Object.create(Object.getPrototypeOf(obj));
  var propNames = Object.getOwnPropertyNames(obj);

  propNames.forEach(function(name) {
    var desc = Object.getOwnPropertyDescriptor(obj, name);
    Object.defineProperty(copy, name, desc);
  });

  return copy;
}

var obj1 = { a: 1, b: 2 };
var obj2 = copy(obj1); // obj2 looks like obj1 now

Polyfill:

// Production steps of ECMA-262, Edition 5, 15.4.4.18
// Reference: http://es5.github.io/#x15.4.4.18
if (!Array.prototype.forEach) {

  Array.prototype.forEach = function(callback, thisArg) {

    var T, k;

    if (this == null) {
      throw new TypeError(' this is null or not defined');
    }

    // 1. Let O be the result of calling toObject() passing the
    // |this| value as the argument.
    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get() internal
    // method of O with the argument "length".
    // 3. Let len be toUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If isCallable(callback) is false, throw a TypeError exception. 
    // See: http://es5.github.com/#x9.11
    if (typeof callback !== "function") {
      throw new TypeError(callback + ' is not a function');
    }

    // 5. If thisArg was supplied, let T be thisArg; else let
    // T be undefined.
    if (arguments.length > 1) {
      T = thisArg;
    }

    // 6. Let k be 0
    k = 0;

    // 7. Repeat, while k < len
    while (k < len) {

      var kValue;

      // a. Let Pk be ToString(k).
      //    This is implicit for LHS operands of the in operator
      // b. Let kPresent be the result of calling the HasProperty
      //    internal method of O with argument Pk.
      //    This step can be combined with c
      // c. If kPresent is true, then
      if (k in O) {

        // i. Let kValue be the result of calling the Get internal
        // method of O with argument Pk.
        kValue = O[k];

        // ii. Call the Call internal method of callback with T as
        // the this value and argument list containing kValue, k, and O.
        callback.call(T, kValue, k, O);
      }
      // d. Increase k by 1.
      k++;
    }
    // 8. return undefined
  };
}

Array.prototype.indexOf()

返回给定元素能找在数组中找到的第一个索引值,否则返回-1

例子:

var a = [2, 9, 9]; 
a.indexOf(2); // 0 
a.indexOf(7); // -1

if (a.indexOf(7) === -1) {
  // element doesn't exist in array
}

Array.prototype.lastIndexOf()

方法返回给定元素能数组中的最后一个的索引,如果不存在则返回 -1. 从数组的后面向前查找,从 fromIndex处开始

Array.prototype.join()

将数组中的所有元素连接成一个字符串,返回字符串,** 不改变原数组**

例子:

let a = ['Wind', 'Rain', 'Fire'];

a.join(); 
// 默认为 ","
// 'Wind,Rain,Fire'

a.join(""); 
// 分隔符 === 空字符串 ""
// "WindRainFire"

a.join("-"); 
// 分隔符 "-"
// 'Wind-Rain-Fire'

console.log(a);
// ['Wind', 'Rain', 'Fire']

Array.prototype.map(callback[, thisArg])

返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组,不改变原数组
回调函数必须有返回值(return),如果没有回返回undefined([undefined, undefined, undefined, undefined])

例子:

// 求数组中每个元素的平方根
var numbers = [1, 4, 9];
// roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9] 
var roots = numbers.map(Math.sqrt);

// 反转字符串
var str = '12345';
Array.prototype.map.call(str, function(x) {
  return x;
}).reverse().join('');  // '54321'

Array.prototype.pop()

删除一个数组中的最后的一个元素,并且返回这个元素, 改变数组

Array.prototype.push()

添加一个或多个元素到数组的末尾,并返回数组新的长度(length 属性值)

Array.prototype.reduce()

接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值,不该变原数组

例子:

/*
 * previousValue: 上一次调用回调返回的值,或者是提供的初始值(initialValue)
 * currentValue: 数组中当前被处理的元素
 * index: 当前元素在数组中的索引
 * array: 调用reduce的数组
 */
[0,1,2,3,4].reduce(function(previousValue, currentValue, index, array){
  return previousValue + currentValue;
});

//数组扁平化
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(function(a, b) {
    return a.concat(b);
});
// flattened is [0, 1, 2, 3, 4, 5]

//阶乘
function factorial (previousValue,currentValue) {
  return previousValue*currentValue
}
var a = [1,2,3,4]
a.reduce(factorial) //24
a.reduce(factorial,10) //240

Array.prototype.reduceRight()

接受一个函数作为累加器(accumulator),让每个值(从右到左,亦即从尾到头)缩减为一个值。(与 reduce()的执行方向相反)

Array.prototype.reverse()

颠倒数组中元素的位置(反序),改变原数组,并返回该数组的引用

Array.prototype.shift()

删除数组的 第一个 元素,并返回这个元素。该方法会改变数组的长度

Array.prototype.slice(begin,end)

浅复制(shallow copy)数组的一部分(从开始到结束,不包括结束)到一个新的数组,并返回这个新数组,不改变原数组

例子:

var a = ['a','b','c','d']
//begin(包含) ,end(不包含)
var b = a.slice(1,3) //["b", "c"]
// begin 可选 如果省略从索引0开始
// end 可选 如果省略则一直提取到原数组末尾
// 将类数组转化成数组
var pNodes = Array.prototype.slice.call(documents.getElementsByTagName("p"))

Array.prototype.sort()
数组的元素做原地的排序,并返回这个数组。 sort 排序可能是不稳定的。默认按照字符串的Unicode码位点(code point)排序, 会改变数组

Array.prototype.splice()

用新元素替换旧元素,以此修改数组的内容,返回新数组, 不改变原数组

例子:

/* 
 * start: 从数组的哪一位开始修改内容
 * deleteCount: 整数,表示要移除的数组元素的个数
 * item: 要添加进数组的元素 
 */
// 从第 3 位开始删除 1 个元素
removed = myFish.splice(3, 1);
// 运算后的myFish:["angel", "clown", "drum", "surgeon"]
// 被删除元素数组:["mandarin"]

// 从第 2 位开始删除 1 个元素,然后插入 "trumpet"
removed = myFish.splice(2, 1, "trumpet");
// 运算后的myFish: ["angel", "clown", "trumpet", "surgeon"]
// 被删除元素数组:["drum"]

Array.prototype.toLocaleString()

返回一个字符串表示数组中的元素。数组中的元素将使用各自的 toLocaleString方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ",")隔开

Array.prototype.toString()

返回一个字符串,表示指定的数组及其元素

判断一个元素是否是数组

if (!Array.isArray) {
  Array.isArray = function(arg) {
    return Object.prototype.toString.call(arg) === '[object Array]';
  };
}

Array.prototype.unshift()

在数组的开头添加一个或者多个元素,并返回数组新的 length 值

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

推荐阅读更多精彩内容

  • Javascript有很多数组的方法,有的人有W3C的API,还可以去MDN上去找,但是我觉得API上说的不全,M...
    顽皮的雪狐七七阅读 3,992评论 0 6
  • 本文转载自@陈铮半年前的博文,原文地址:JavaScript Array 原型方法 大盘点 数组是一个超常用的数据...
    浙大javascript联盟阅读 711评论 0 4
  • 第五篇(年后冲刺) 耀英耀红马上就要考中学了,他们都在努力学习,耀英每天早上很早就起床背书,写卷纸,由于爸...
    MrYichen阅读 174评论 0 0
  • 感谢阅读!本文乃作者个人原创,未经允许谢绝转载,欢迎转发分享。 那天一早醒来,手机滴滴滴响个不停,打开一看,是大学...
    醒来么么阅读 340评论 0 1
  • 悄悄的,悄悄的逝去了时间然后遗留下一片空白的时间,等到爱来的时候,我们刚好长发及腰,然后带着爱的人走向未来。 ...
    阿昕小章鱼阅读 201评论 0 1