数组Array基础知识

数据类型new与不new的区别
伪数组
数组api
查看Array对象公共属性

基本数据类型new不new的区别

new String(x)和String(x)的区别

1
2
3
4
5
6
String(1) //"1" 变成字符串
String(false) // 'false'
String(null) // 'null'
new String(1) // String {"1"} 变成String对象
new String('sss') // String {"sss"}

new Number(x)和Number(x)的区别

1
2
3
4
5
6
7
8
9
10
Number('3') //3 变成数字
Number('sss') //NaN NaN也是数字类型
Number(true) //1
Number(false) //0
Number(null) //0
Number(undefined) //NaN
new Number('123') //Number {123} 变成Number对象
new Number(111) //Number {111}

复杂数据类型new不new的区别

new OBject(x)和Object(x)的区别【没区别】


1
2
3
4
5
6
7
8
9
10
11
Object(1) // Number {1} 传入数字则变成Number对象
new Object(1) // Number {1} 与上面没区别
Object('sss') // String {"sss"} 传入字符串则变成String对象
new Object('sss') // String {"sss"}
Object() //{} 什么都不传就是空对象
new Object() //{}
Object(false) // Boolean {false} 传入布尔值则变成Boolean对象
new Object(false) // Boolean {false}

数组Array

1
2
3
4
5
6
7
8
9
10
11
12
13
var arr = Array(3) // [undefined,undefined,undefined] 【生成length为3,每个值都是undefined的数组】
arr[0] //undefined
arr[1] //undefined
arr[2] //undefined
'0' in arr //false 从内存图可以看出,在地址99的数据里只有length和__proto__
'length' in arr //true
'__proto__' in arr //true
arr.__proto__ == Array.prototype //arr是由Array构造的,所以它的__proto__指向Array的公用属性
//true 生成的数组的__proto__指向Array的公用属性(原型prototype)
//这个公用属性中有push方法、shift方法等


1
2
3
4
5
6
7
var arr = Array(3) // [undefined,undefined,undefined]
1个参数时表示生成长度为length、每一项的值为undefined的数组
var arr = Array(3,3) // [3,3] 多于1个参数时,表示每一项的值
var arr = new Array(3) 跟不加 new 一样的效果
var arr = new Array(3,3) 跟不加 new 一样的效果

函数Function

1
2
3
4
5
6
7
8
9
10
11
var fn1 = function (a,b) {
return a+b;
};
fn1(5,9);// 14
--------
var fn2 = Function('a','b','return a-b');//参数和方法体都写成字符串的形式
等同于
var fn2 = new Function('a','b','return a-b');//加不加new都一样
fn2(10,3) //7

总结 new不new的区别

  • 基本数据类型不加new 则返回基本类型

    1
    String(1) // '1'
  • 基本数据类型加new 则返回一个对象

    1
    new Number('123') //Number {123} 变成Number对象
  • 复杂数据类型加不加new都一样

    1
    2
    Object('sss') // String {"sss"} 传入字符串则变成String对象
    new Object('sss') // String {"sss"}

伪数组

  • arguments 对象是伪数组
  • document.querySelectAll(‘div’) 返回的对象是伪数组
    上面两个有以下这些特征:

1.有 0:xx,1:xx,2:xx,3:xx…n:xx,length:xx 这些 key 的对象
2.他们的proto不链接到数组的公用属性Array.prototype,即他们的原型链中没有Array.prototype

这样的对象就是伪数组

1
2
3
4
5
6
7
8
function fn() {
console.log(arguments)
}
fn(1,3,5,7);
//arguments有0,1,2...,length这些key,
但是它的__proto__没有指向Array的公用属性Array.prototype,而是指向Object.prototype
fn.push(9) // 报错,伪数组没有数组的api

instanceof判断是不是数组

instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
换句话说,instanceof用来测试一个对象的proto是否指向构造函数(Array,Function,Object等)的共有属性(prototype)

1
2
3
4
5
6
7
var arr = [1,2,3];
arr instanceof Array; //true
arr instanceof Function; //false
//伪数组的原型链中没有Array的prototype属性
var lis = document.querySelectorAll('li');
lis instanceof Array;//false

数组的操作(api)

  • 数组就是数据的有序集合
  • 数组就是原型链中有 Array.prototype 的对象

遍历数组获取value和index用forEach

arr.forEach(function (value,index) {执行函数体/return 返回值});
forEach只用来操作数据,没有return返回值
map可以有返回值

forEach的用法与map方法一致,接受三个参数:value、index、整个数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var colors = ['red', 'green', 'blue'];
colors.forEach(function (value,index) {
console.log(value);
});
//箭头函数写法:colors.forEach((value,index) => console.log(value));
// red
// green
// blue
-------
var colors = ['red', 'green', 'blue'];
colors.forEach(function (value,index) {
console.log(index + ':'+ value);
});
//0:red
//1:green
//2:blue

forEach的原理:

排序sort

  • sort用的快速排序
  • 默认的sort会将数字先转成字符串,再按照字典顺序进行从小到大排序,所以会有bug

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    ['d', 'c', 'b', 'a'].sort()
    // ['a', 'b', 'c', 'd']
    [4, 3, 2, 1].sort()
    // [1, 2, 3, 4]
    [11, 101].sort()
    // [101, 11] 先比较最前面的数,都是1,再比较第二位数,js误以为101小于11
    [10111, 1101, 111].sort()
    // [10111, 1101, 111] 先比较最前面的数,都是1;再依次比较后几位数,有bug
  • 如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    从小到大排序a-b
    [10111, 1101, 111].sort(function (a, b) {
    return a - b;
    })
    // [111, 1101, 10111]
    --------
    从大到小排序b-a
    [10111, 1101, 111].sort(function (a, b) {
    return b - a;
    })
    [10111, 1101, 111]
  • 根据给定的依据进行排序

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var students = ['小明','小红','小花'];
    var scores = { 小明: 59, 小红: 99, 小花: 80 };
    students.sort(function(a,b) {
    return scores[a]-scores[b]; //按照scores从小到大排序
    });
    //["小明", "小花", "小红"]
    students.sort(function(a,b) {
    return scores[b]-scores[a];//按照scores从大到小排序
    });
    //["小红", "小花", "小明"]


1
2
3
4
5
6
7
8
9
10
11
12
[
{ name: "张三", age: 30 },
{ name: "李四", age: 24 },
{ name: "王五", age: 28 }
].sort(function (o1, o2) {
return o1.age - o2.age;
})
// [
// { name: "李四", age: 24 },
// { name: "王五", age: 28 },
// { name: "张三", age: 30 }
// ]

join 数组变字符串

join方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分隔。

1
2
3
4
5
var a = [1, 2, 3, 4];
a.join(' ') // '1 2 3 4'
a.join('xx') // "1xx2xx3xx4"
a.join() // "1,2,3,4"

数组变字符串更简单的办法:

1
2
3
4
var a = [1, 2, 3, 4];
a+''; // "1,2,3,4"
a+'3'; // "1,2,3,43"

cancat连接多个数组

concat方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。

1
2
3
4
5
6
7
8
9
10
11
['hello'].concat(['world'])
// ["hello", "world"]
['hello'].concat(['world'], ['!'])
// ["hello", "world", "!"]
[].concat({a: 1}, {b: 2})
// [{ a: 1 }, { b: 2 }]
[2].concat({a: 1})
// [2, {a: 1}]

concot用来复制一个数组,由于concat返回的是一个新数组,因此虽然复制原数组,但两者不相等

1
2
3
var a = [1,2,3];
var b = a.concat([]); // b = [1,2,3]
a == b; // false

数组相加

数组的相加,先将每个数组转变成字符串,然后连接起来

1
[1,2,3]+[4,5,6] // "1,2,34,5,6"

map

map方法将数组的所有value依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。原数组不变
forEach没有返回值,map有返回值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var numbers = [1, 2, 3];
var newNum = numbers.map(function (value) {
return value + 1;
});
newNum; // [2,3,4]
numbers; // [1, 2, 3] 原数组不改变
上面代码中,numbers数组的所有成员依次执行参数函数,运行结果组成一个新数组返回,原数组没有变化。
------------
也可以像forEach一样依次for循环执行
numbers.map(function (value) {
console.log(value + 3);
});
// 4
// 5
// 6

map有三个参数:value、index和数组本身。

1
2
3
4
[1, 2, 3].map(function(value, index, arr) {
return value * index;
});
// [0, 2, 6]

用箭头函数=>可以简写为:

1
2
var arr = [2,3,4];
arr.map(value => value+3); // [5, 6, 7]

map方法还可以返回包含对象的数组

1
2
3
4
5
6
7
8
var arr = [2,3,4];
arr.map(function(value,index){
return {
'下标':index,'值':value
}
});
// [ {下标: 0, 值: 2}, {下标: 1, 值: 3}, {下标: 2, 值: 3} ]

filter筛选出

filter方法对数组中的每一项进行筛选出,满足条件的value组成一个新数组返回。

它的参数是一个函数,所有数组value依次执行该函数,返回结果为true的value组成一个新数组返回。

该方法不会改变原数组。

1
2
3
4
[1, 2, 3, 4, 5].filter(value => {
return (value > 3); //结果为true的value组成一个新数组返回
})
// [4, 5]

filter方法可以接受三个参数:value,index和整个数组。

1
2
3
4
[1, 2, 3, 4, 5].filter((value, index, arr) => {
return index % 2 == 0;
});
// [1, 3, 5]

过滤falsy值

1
2
3
var arr = [1,2,'',4,0,undefined];
var newArr = arr.filter(v=>v)
//newArr===[1, 2, 4]

先filter过滤再用map操作

1
2
3
4
5
6
7
8
var a = [1,2,3,4,5,6,7,8,9];
a.filter(nfunctio(value){
return value > 5;
}).map(function(value){
return value*2;
})
// [12, 14, 16, 18]

压缩累计reduce,reduceRight

reduce方法和reduceRight方法依次处理数组的每个value,最终压缩累计为一个值。它们的差别是,reduce是从左到右处理(从第一个value到最后一个value),reduceRight则是从右到左(从最后一个value到第一个value),其他完全一样。

reduce方法可以可以简化用for循环来累计的运算(比如求数组之和)

1
2
3
4
5
6
7
8
9
10
var arr = [1, 2, 3, 4, 5];
arr.reduce(function (sum, value) {
console.log(sum, value);
return sum + value;
}, 0) //默认初始值为0,可以省略不写
// 1 2
// 3 3
// 6 4
// 10 5
//最后结果:15

用箭头函数=>简化:

1
2
arr.reduce((sum,value) => sum+value,0);//初始值为0
//最后结果:15

reduce可以设置初始值

1
2
3
4
[1, 2, 3, 4, 5].reduce(function (a, b) {
return a + b;
}, 10); // 从10开始累加
// 最后结果:25

计算所有奇数之和:

1
2
3
4
5
6
var a = [1,2,3,4,5,6,7,8,9];
a.reduce( function(sum,value) {
value = value%2 == 0 ? 0 : value;
return sum + value;
},0)

reduce替代map

设置初始值为空数组[]

1
2
3
4
5
6
7
8
var arr = [2,3,4];
将数组里的每一项乘以2,然后返回一个新数组
arr.reduce(function(sum, value) {
sum.push(value*2); //push到初始值内
return sum;
},[]) //初始值是个空数组
// [4, 6, 8]

reduce替代filter

设置初始值为空数组[]

1
2
3
4
5
6
7
8
9
10
var arr = [1,2,3,4,5,6,7,8,9];
用reduce过滤出所有的偶数,然后返回新数组
arr.reduce(function(sum,value){
if(value%2==0){
sum.push(value);
}
return sum
},[])
// [2, 4, 6, 8]

数组中是否含有某个值

顺带一提,字符串用str.indexOf(value)来判断是否含有某个字符

1
2
3
'abcde'.indexOf('c') // 2
'abcde'.indexOf('f') // -1
'abcde'.indexOf('bcd') // 1

arr.includes()

语法:arr.includes(value [,startIndex])

1
2
3
[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false
[1, 2, NaN].includes(NaN); // true

Jquery的$.inArray()方法

语法:$.inArray( value, array [, startIndex ] )

1
2
3
var arr = [1,2,'hi',3,'world'];
console.log( $.inArray( 'hi', arr) ) // 2 说明'hi'在arr的第2位
console.log( $.inArray( 5, arr) ) // -1 说明arr中没有数字5

every()

arr.every((item,index) => {}) 方法用于检测数组所有元素是否都符合指定条件,所有符合则返回true,只要有一个不符合就返回false

1
2
3
4
5
6
let ages = [32, 33, 16, 40];
ages.every(age => age>18);//false
//对象中的数组
let obj = {a: [{b:1}, {b:2}] };
obj.a.every(item => item.b > 0);//true

some()

some() 方法用于检测数组中的元素其中1个是否有满足指定条件,只要有一个元素满足条件,则表达式返回true

1
2
let ages = [3, 10, 18, 20];
ages.some(age => age>18);//true

find()

返回数组中符合条件的第一个元素的值,如果没有符合条件的元素则返回 undefined

1
2
3
4
5
6
7
8
let arr = [12,1,5,99,6];
arr.find( item => item>13 );//99
const x = arr.find( item => item>13 );
//如果数组中没有元素大于13,则返回undefined
if(x){
//doSomething;
}

findIndex()

返回数组中符合条件的第一个元素的位置,如果没有则返回-1

1
2
3
4
5
6
7
8
9
10
11
let arr = [12,1,5,99,6];
arr.findIndex( item => item>13 );//3
arr.findIndex( item => item == 1 );//1
类似于
arr.forEach((item,index) => {
if(item > 10) {
console.log(index);
}
})
//0,3

删除具体某个值

1
2
3
4
5
6
7
8
9
var arr = ["George", "John", "James", "Adrew", "Martin"];
//替换
arr.splice( arr.indexOf( 'James' ), 1, 'Tom' );
arr;//["George", "John", "Tom", "Adrew", "Martin"]
//删除
arr.splice( arr.indexOf( 'Adrew' ), 1);
arr;//["George", "John", "Tom", "Martin"]
-------------本文结束感谢您的阅读-------------