数组常用方法大全(es5 之前 - es5 - es6),以及一些方法的源码实现

数组

1 什么是数组

存储一组关联数据

2 数组定义方式

  1. 数组直接量(常用)
var arr = [] ;
var arr2 = [10,20,30];
  1. 通过new创建
var arr3 = new Array()var arr4 = new Array(10,20,30)
console.log(arr4) // [ 10, 20, 30 ]

3 数组访问

数组名[下标] 下标 0 1 2 3 …;数组长度可以通过数组名.length访问

4 数组元素的遍历

1、for 循环

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

2、for in 对对象进行访问 ,数组也是对象

var arr4 = [1,3,9,11];
for(var i in arr4) {
     console.log(i+":"+arr4[i]); // i 0 1 2 3 数组下标 
     //console.log(arr4[i]);    
 }

示例:

var obj = {
     a: 100,
     b: 200
 }
 for(var k in obj) {
     console.log(k); // 打印为 a , b
     //console.log(obj.k); 用法错误,k是变量,只能通过[]
     console.log(obj[k]);  
 }

5 二维数组

数组的元素可以是任何合法的值,甚至元素可以是数组

var arr = [[10,20],30,40];

6 数组操作

push()

向数组末尾添加一个或多个元素,原数组变为添加后的数组,返回值是改变后的数组长度

var arr = [1, 2, 3];
// arr[arr.length] = 4;
var res = arr.push(4, 5);
console.log(arr); // [ 1, 2, 3, 4, 5 ]
console.log(res);  //5
unshift()

向数组前面添加一个或多个元素,原数组变为添加后的数组,返回值是改变后的数组长度

var arr = [1, 2, 3];
var res2 = arr.unshift(10, 20);
console.log(arr);  // [10,20,1,2,3,4,5]
console.log(res2);  // 5
pop()

删除数组最后一个元素,返回被删除的元素,无参,原数组变为删除后的数组

var arr = [1, 2, 3];
var res3 = arr.pop();
console.log(arr);  // [ 1, 2 ]
console.log(res3); // 3
shift()

删除数组第一个元素,返回被删除的元素,原数组变为删除后的数组

var arr = [1, 2, 3];
var res4 = arr.shift();
console.log(arr);  // [ 2, 3 ]
console.log(res4); // 1
splice()

可以删除 和 添加 元素,具体情况如下

function fnSplice() {
    var arr = [11, 34, 32, 56, 37];
    // 1 从角标为1开始删除2个元素,返回值是删除元素组成的数组,原数组变为删除后的数组
    // var res1 = arr.splice(1,2);
    // console.log(arr);  // [ 11, 56, 37 ]
    // console.log(res1); // [ 34, 32 ]
    
    //  2 从角标为2开始,添加元素,第二个参数为0,返回值是删除元素组成的数组
    // var res2 = arr.splice(2,0,10);
    // console.log(arr);  // [ 11, 34, 10, 32, 56, 37 ]
    // console.log(res2); // []
    
    // 3 替换,返回值是被替换的数组,原数组变为替换后的数组
    var res3 = arr.splice(2, 2, 100, 200);
    console.log(arr);  // [ 11, 34, 100, 200, 37 ]
    console.log(res3); // [ 32, 56 ]
}
fnSplice();
slice()

功能:截取数组

返回值:返回一个新数组(截取的),原数组不改变

参数:start 从什么位置开始

       end 截至位置 不包括end ;如果没有end,切分的数组包含从 start 到数组结束的所有元素
var arr = [10, 20, 30, 40];
var res = arr.slice(1, 3);
console.log(arr, res);  //[ 10, 20, 30, 40 ] [ 20, 30 ]
//console.log(arr.slice(2));  [30, 40] 
join()

把数组的元素用指定的符号拼接成一个大的字符串,不传参数默认以逗号连接

var arr2 = [-10, 20, 34, 22];
var res2 = arr2.join(); // '-10,20,34,22'
var res3 = arr2.join("-"); // '-10-20-34-22'
console.log(res2, res3);
concat()

连接数组,返回是一个新数组,原数组都不变

var arr3 = [1, 2, 3];
var arr4 = [4, 5, 6];
var arr5 = [7, 8, 9];
var arr6 = arr3.concat(arr4, arr5, 10);// [1,2,3,4,5,6,7,8,9,10]
console.log(arr6);
reverse()

对数组元素进行逆序,会改变原数组,返回值就是原数组改变后的结果

var arr3 = [1, 2, 3];
var res4 = arr3.reverse();
console.log(arr3);  //[3,2,1]
console.log(res4);  //[3,2,1]
console.log(res4 === arr3); // true

var arr7 = [];
for (var i = 0; i < arr3.length; i++) {
    arr7.push(arr3[i]);
}
//console.log(arr7); [1,2,3]
//逆序原理
var index = 0;
for (var i = arr7.length - 1; i >= 0; i--) {
    arr3[index++] = arr7[i];
}
console.log(arr3);

7 es5数组操作

forEach()

对数组进行遍历,无返回值

var arr = [10,30,50,70];
arr.forEach(function(item,index,arr) {
    //item表示元素、index表示下标、arr为数组
    //console.log(item,index); // 10 0
    //console.log(arr);  
    if(item >= 20) {
        console.log(item);    
    }
});
// 找数组中最小值
var arr2 = [-2,34,0,-5,6];
var min = arr2[0];
arr2.forEach(function(item,index,arr) {
    if(item < min) {
        min = item;
    }
});
alert(min);
indexOf()

判断一个元素是否存在数组中,存在的话,返回元素所在数组下标,不存在返回-1

var arr2 = [-2,34,0,-5,6];
var index = arr2.indexOf(34);
var index2 = arr2.indexOf(134);
console.log(index,index2); // 1 -1

// 练习 数组去重  [10,23,10,34,23,11] 返回 [10,23,34,11]
var arr = [10,23,10,34,23,11];
var res = [];
arr.forEach(function(item, index, arr) {
    if(res.indexOf(item) === -1) {
        res.push(item);
    }
});
console.log(res);
filter()

对原数组进行过滤,由每次函数返回值为true对应的元素组成一个新数组,原数组不变

var array = [10,23,21,34,44,88];
var res = array.filter(function(item,index,arr) {
    console.log(item);
    return item%2 === 0; //控制返回的值,保留偶数,return 1 为全部保留,0为都不保留
});
console.log(res); // [ 10, 34, 44, 88 ]
console.log(array); // [ 10, 23, 21, 34, 44, 88 ]
map()

返回新的数组,新数组长度与原数组长度一样,新数组的每个元素等于每次函数的返回值

var array = [10, 23, 21, 34, 44, 88];
var res2 = array.map(function (item, index, array) {
    //return 0;
    return item - 5; //返回值每个数减5
});
console.log(array); // 原数组不变 [ 10, 23, 21, 34, 44, 88 ]
console.log(res2); // [ 5, 18, 16, 29, 39, 83 ]
reduce()
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)

参数:

参数描述
function(total,currentValue, index,arr)必需。用于执行每个数组元素的函数。
参数描述——
total必需。初始值, 或者计算结束后的返回值。
currentValue必需。当前元素
currentIndex可选。当前元素的索引
arr可选。当前元素所属的数组对象。
initialValue可选。传递给函数的初始值
var array = [10, 23, 21, 34, 44, 88];
var sum = array.reduce(function (prev, next, currentIndex, arr) {
    //console.log(arr); 
    console.log(prev + "----" + next);
    return prev + next;
}, 0); // 当第二个参数不传值时 prev 第一次默认是数组第一个元素 
// 传入第二个参数时 prev第一次就是该参数
console.log(sum);  // 220

/*[10,23,21,34,44,88]
  10----23
  undefined----21
  undefined----34
  undefined----44
  undefined----88

  第一次 prev指向数组第一个元素
        next指向数组第二个元素
  后面 prev表示上一次函数的返回值,next每次指向下一个元素

  prev 10 next 23 return 33
  prev 33 next 21 return 33+21
  prev 33+21 next 34 return 33+21+34
  prev 33+21+34 next 44 return 33+21+34+44
  prev 33+21+34+44 next 88 return 33+21+34+44+88
*/

8 es6数组操作

Array.from()

把数组或类数组转成数组,并复制一份

function fn() {
     //下面两种方式将....转为数组 
     let arr = Array.from(arguments);
     //let arr = [...arguments];
     console.log(arr);  
}
fn(1,2,3);
Array.of()

给数组添加值

console.log(new Array(3).length);// [,,]  其中3代表长度 长度为3

console.log(Array.of(3).length);// 1     [3]  3是元素  长度为1

console.log(new Array(3,2));  // [3,2]
console.log(new Array(3,2).length); // 2
fill() 填充
let arr = [1,2,3,4,5]; 
arr.fill('a',1,3);  //[1,a,a,4,5]  用‘a’填充下标1-3(不包含3)
console.log(arr);
copyWithin()替换
let arr2 = [1,2,3,4,5];
arr2.copyWithin(0,2,4);  
console.log(arr2); // [3, 4, 3, 4, 5]  用下标2-4(不包含4)的元素从0开始替换
find() findIndex() some() every()
// find() findIndex() es5 some/every
let res = [2,3,3].findIndex(item => item > 1 );   //找到第一个返回值为true的值的下标作为返回值。找不到返回-1
console.log(res); // 0
        
let res2 = [1,2,3].some(item=>item>12);
console.log(res2);   //某个值大于12就返回true
        
let res3 = [1,2,3].every(item=>{
       console.log(123);   
       return item<2;    //每个值小于2就返回true
});
console.log(res3);
ES6 keys()&values()&entries()遍历键名、遍历键值、遍历键名+键值
for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1    
for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'    
for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

拓展:

将函数的实际参数转换成数组的方法

方法一:var args = Array.prototype.slice.call(arguments);

方法二:var args = [].slice.call(arguments, 0);

方法三:

var args = []; 
for (var i = 1; i < arguments.length; i++) { 
    args.push(arguments[i]);
}

转成数组的通用函数

var toArray = function(s){
    try{
        return Array.prototype.slice.call(s);
    } catch(e){
        var arr = [];
        for(var i = 0,len = s.length; i < len; i++){
            //arr.push(s[i]);
            arr[i] = s[i];  //据说这样比push快
        }
         return arr;
    }
}

源码实现

// push 实现
function push(arr,...val) {
      //var start = arr.length;
      for(var i = 0; i < val.length; i++) {
           arr[arr.length] = val[i];
      }
      return arr.length;
} 
var arr = [1,2,3];
var len = push(arr,4,5,6,7);
console.log(arr); // [1,2,3,4,5,6,7]
console.log(len); // 7

手写filter map reduce方法

// filter 实现
function filter(arr, callback) {
    if(!Array.isArray(arr) || !arr.length || typeof callback !== 'function') {
        return [];
    } else {
        let res = [];
        for(let i=0; i<arr.length; i++) {
            // 返回结果为真
            if(callback(arr[i], i, arr)) {
                res.push(arr[i]);
            }
        }
        return res;
    }
}

// 实现 map 方法
function map(arr, callback) {
    if (!Array.isArray(arr) || !arr.length || typeof callback !== 'function') {
        return [];
    } else {
        let res = [];
        for (let i=0; i<arr.length; i++) {
            res.push(callback(arr[i], i, arr));
        }
        return res;
    }
}

// 实现 reduce
function reduce(arr, callback, initValue) {
    if(!Array.isArray(arr) || !arr.length || typeof callback !== 'function') {
        return [];
    } else {
        let hasInitValue = initValue !== undefined;
        let prexValue = hasInitValue ? initValue : arr[0];

        for (let i = hasInitValue ? 0 : 1; i < arr.length; i++) {
            prexValue = callback(prexValue, arr[i], i ,arr)
        }
        return prexValue;
    }
}

数组拓展知识

在看别人代码时,发现有这么个写法:[].slice.call(arguments, 0),这到底是什么意思呢?

1、基础

1)slice() 方法可从已有的数组中返回选定的元素。

start:必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。

end:可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。

返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject中的元素。该方法并不会修改数组,而是返回一个子数组。

2)call()apply()方法都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。apply和call方法的第一个参数都是特定的作用域第二个参数不同,apply第二个参数可以是Array的实例,也可以是arguments对象。call方法需要逐个列出需要传递的参数。

3)arguments对象指数与数组类似(它并不是Array的实例),但是可以使用方括号语法访问每一个元素,使用length来确定传递进来多少个参数。

4)Array.prototype.slice.call()可以理解为:改变数组的slice方法的作用域,在特定作用域中去调用slice方法,call()方法的第二个参数表示传递给slice的参数即截取数组的起始位置。

2、原理

Array.prototype.slice.call(arguments)能将具有length属性的对象(key值为数字)转成数组。[]是Array的示例,所以可以直接使用[].slice()方法。

var obj = {0:'hello',1:'world',length:2};
console.log(Array.prototype.slice.call(obj,0));//["hello", "world"]

没有length属性的对象

var obj = {0:'hello',1:'world'};//没有length属性
console.log(Array.prototype.slice.call(obj,0));//[]
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值