JavaScript系列之内置对象(一):Array

简介

Array是JavaScript创建数组的全局对象。此篇省略基本操作,主要写API,这篇文章提到的拷贝都是属于浅拷贝

使用前需要注意:

  • 数组的长度和元素类型都是不固定的
  • 其数据在内存中可以是不连续的
  • 如果这些特点给你带来不便,可以使用类型数组TypedArary
  • 索引只能是整数
  • 通过非整数形式(arr['length']arr.length)操作数组,操作的并不是数组元素,而是数组的属性

属性

只有三个属性,但是这里只介绍两个:lengthprototypeprototype允许我们可以向所有的Array对象统一添加新的属性和方法,比如添加一个自定义的取出数组中的第一个元素:

if (!(first in Array.propotype)) {
    Array.propotype.first = () => {
        return this[0]
    }
}

全局API

from

from(obj[, callback, thisAry])方法用来根据一个可迭代对象创建一个新的数组。

  • obj:想要转化成数组的伪数组对象或者可迭代对象
  • callback:参数可选。如果指定了此回调函数,那么from方法每次对迭代元素进行转换的时候都会执行一次此方法
  • thisAry:指定callback执行时的this对象

isArray

判断是否是数组,当检测Array实例时,Array.isArray 优于 instanceof,因为Array.isArray能检测iframes

var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]

// Correctly checking for Array
Array.isArray(arr);  // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false

of

根据一组参数创建数组:

Array.of(...item);// 返回新数组

实例 API

修改器 API

此标题下的API将会修改数组对象本身的值。

copyWithin

对一个数组对象进行浅拷贝,不会修改其大小。

arr.copyWithin(target, start, end);
  • target:拷贝之后需要放到数组中的哪个位置,如果大于length,将不会发生拷贝行为,如果大于starttarget的值将会被修改成符合length范围内的值。如果为负数,则从尾部开始计算
  • start:浅拷贝开始的位置,如果被忽略,其值等于0,如果为负数,则值:start + lengthend也是如此
  • end:浅拷贝结束的位置,如果被忽略,其值等于length
// array
let arr = ['z', 'x', 'c'];
arr.copyWithin(2, 0, 2);
console.log(arr) // ['z', 'x', 'z']

具体实现:

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;
  };
}

fill

arr.fill(value[, start, end])

将数组中指定位置区间的元素替换成指定的值:

let arr = [1, 2, 3];
arr.fill(0, 2, 3); // [1, 0, 0]

具体实现:

if (!Array.prototype.fill) {
  Object.defineProperty(Array.prototype, 'fill', {
    value: function(value) {

      // 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-7.
      var start = arguments[1];
      var relativeStart = start >> 0;

      // Step 8.
      var k = relativeStart < 0 ?
        Math.max(len + relativeStart, 0) :
        Math.min(relativeStart, len);

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

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

      // Step 12.
      while (k < final) {
        O[k] = value;
        k++;
      }

      // Step 13.
      return O;
    }
  });
}

pop / push

pop是删除数组中的最后一个元素并返回这个元素,push是在数组最后添加一个或多个元素并返回新长度

shift / unshift

shift是删除数组中的第一个元素并返回此元素,unshift是在数组开头添加一个或多个元素并返回新长度

splice

splice是在数组的任意位置添加或删除任意个元素。

arr.splice(start[, end, ...item])

如果item不指定则是删除元素

sort / reverse

sort是将数组进行排序,可以选择传入一个自定义排序函数:

arr.sort((a, b) = {
  if (a < b ) {           // 按某种排序标准进行比较, a 小于 b
    return -1;
  }
  if (a > b ) {
    return 1;
  }
  // a must be equal to b
  return 0;
})

reverse是将数组的顺序颠倒

访问 API

访问API是不会修改数组本身的。

concat / slice

concat会将此数组和其他数组的元素进行合并,返回一个新数组,但参与合并的数组的值不会发生改变。

arr.concat(...arr1); // 返回的是一个浅拷贝对象,对新数组进行操作不会对原数组有任何改变

slice是抽取当前数组中的一段元素抽出合成一个新的数组,接受startend参数。

join / toString / toLocalString

将数组转成字符串,toString使用的是默认参数的joinjoin方法接收一个参数作为数组转成字符串形式的分隔符

let arr = ['zeng', 'xiao', 'chen'];
arr.join(','); // "zeng,xiao,chen"

includes / indexOf / lastIndexOf

判断数组中是否存在指定元素,inclueds返回booleanindexOflastIndexOf返回number,返回元素所在的索引值,不存在则是-1,也可以指定开始查找的位置。

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

迭代API

不要轻易尝试在迭代的回调函数中对数组进行更改

filter / map

  1. filtermap都返回一个新的数组。
  2. filter是判断元素,map是处理元素

filter会跟forEach一样,但是它在迭代的同时,会返回符合条件的数组元素(true),并在迭代结束后将这些元素组合成一个数组对象并返回:

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

map会返回处理后的元素:

// 求平方根
let numbers = [1, 4, 9];
let roots = numbers.map(Math.sqrt);
// roots is now [1, 2, 3]
// numbers is still [1, 4, 9]

forEach / every / some

forEach方法为数组中的每个元素做一次遍历。它接收两个参数,第一个是回调函数,回调函数接收三个参数:

  • currentValue:当前正在被迭代的元素
  • indexcurrentValue在数组中的索引位置
  • array:当前被循环的数组
    还有一个是指定在回调参数中的this对象,**如果不指定,在非严格模式下是全局对象,严格模式下是undefined,语法如下:
arr.forEach((currentValue, index, array) => {
    // ....
}, Array);

every方法同forEach方法,不过forEach没有返回值,而every返回boolean,返回false的时候迭代立即结束。

someevery的规则相反,返回true的时候迭代立即结束。

entries / keys / values

entries方法返回此数组的可迭代对象,可迭代对象中包含了数组的元素索引和元素本身:

var arr = ["a", "b", "c"];
var iterator = arr.entries();
// undefined

console.log(iterator);
// Array Iterator {}

console.log(iterator.next().value); 
// [0, "a"]
console.log(iterator.next().value); 
// [1, "b"]
console.log(iterator.next().value); 
// [2, "c"]

//==============================

function sortArr(arr) { // 二维数组排序
    var goNext = true;
    var entries = arr.entries();
    while (goNext) {
        var result = entries.next();
        if (result.done !== true) {
            result.value[1].sort((a, b) => a - b);
            goNext = true;
        } else {
            goNext = false;
        }
    }
    return arr;
}

var arr = [[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]];
sortArr(arr);

keys也是返回一个迭代对象,但是只包含数组元素的索引并作为键,values同它差不多:

let arr = ["a", "b", "c"];

let iterator = arr.keys();
// undefined

console.log(iterator);
// Array Iterator {}

console.log(iterator.next()); 
// Object {value: 0, done: false}

console.log(iterator.next()); 
// Object {value: 1, done: false}

console.log(iterator.next()); 
// Object {value: 2, done: false}

console.log(iterator.next()); 
// Object {value: undefined, done: true}

find / findIndex

find找到第一个满足回调函数的元素,并返回其值,没有则返回undefined

findIndex找到第一个满足回调函数的元素,并返回其在数组中的索引位置,没有则返回-1

function isBigEnough(element) {
    return element >= 15;
}

var ret1 = [12, 5, 8, 130, 44].findIndex(isBigEnough);
console.log(ret1);

raduce / reduceRight

raduce方法从左到右执行回调函数,并把上次回调函数的结果放在一个寄存器中,最后返回这个寄存器的值。

接收两个参数:callbackinitialValue,回调方法接收四个值:

  • accumulator:累加器,累加上一次回调返回的值。
  • currentValue:当前元素
  • currentIndex:可选,当前索引,如果指定了initialValue,它的初始索引为1
  • array:可选,当前数组

initialValue可选。指定回调初始值,没有则是数组的第一个元素

let val = [0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){
  return accumulator + currentValue;
});
// val = 10



let arr = ['z', 'x', 'c'];
let reduce = arr.reduce((a, value) => {
    return a + value;
}, "我的名字首拼是:");
console.log(reduce); // 我的名字首拼是:zxc
Last modification:March 11th, 2018 at 05:27 pm
If you think my article is useful to you, please feel free to appreciate

2 comments

  1. godaddy优惠码

    朋友 交换链接吗

    1. 曾小晨
      @godaddy优惠码

      看交换条件哈,在友链界面那里有写条件

Leave a Comment Cancel reply