一、数组空位与undefined
数组空位:数组的某一个位置没有任何值
产生空位的原因:数组中两个逗号之间不放任何值;用new Array()的方法,参数里是个数字;通过一个不存在的下标去增加数组;增加数组length属性的值。
空位的特点:
1. 空位也是数组的数据;
2. 空位在读取的时候为undefined; 如果数组最后一个数据有逗号,并不会产生空位(非ie6,7,8),应该尽量避免在后面加上逗号;
3. 数组的空位与某个位置为undefined是不一样的(在循环的时候)
a. for,for...of循环会把空位处理成undefined
b.entries,keys,values,find,findIndex会将空位处理成undefined
c. for...in,forEach,map,filter,Object.keys(),every,some都会忽略空位
注意:数组的一些方法对于空位的处理是不一样的,所以数组里最好不要出现空位,或者用undefined。es6中则是明确将空位转为undefined。
<script>
let color = ['red', , 'blue', undefined];
console.log(color); //(4) ["red", empty, "blue", undefined]
console.log(
color[length], //red
color[1], // undefined
color[1] === color[3] //true
)
let arr = new Array(3);
console.log(arr) //(3) [empty × 3]
arr[6] = '';
console.log(arr); //(7) [empty × 6, ""]
arr.length = 10;
console.log(arr); //(10) [empty × 6, "", empty × 3]
//转成undefined
for (var i = 0; i < color.length; i++) {
console.log('key,' + i + ',value,' + color[i]);
//key,0,value,red
//key,1,value,undefined
//43 key,2,value,blue
//43 key,3,value,undefined
}
//忽略空位
for (var attr in color) {
console.log('key,' + attr + ',value,' + color[i]);
//key,0,value,undefined
//key,2,value,undefined
//key,3,value,undefined
}
</script>
二、es6数组解构赋值
从数组中提取值,按照对应的位置,对变量进行赋值,本质上是“模式匹配”。只要等号两边的模式相同,左边的变量就会被赋予右边对应的值。可以代替逗号声明的变量;如果右边缺少数组用undefined代替,如果右边是多出数据那就忽略,如果右边不是数组,报错;当用默认值的时候,右边对应的值必需为undefined,不然默认值就不会生效。
<script>
{
const [name, [age], sex] = ['davina', [18], '女'];
console.log(name, age, sex); //davina 18 女 一一对应
}
{
//右边少一个
const [width, , height, color] = ['20px', , '30px'];
console.log(width, height, color); //20px 30px undefined
}
{
//右边多一个
const [width, , height, color] = ['20px', , '30px', 'pink', 'blue'];
console.log(width, height, color); //20px 30px pink
}
{
const [a,b,c]='davina';
console.log(a,b,c); //d a v
}
{
// const [a,b=2,c] = [1,undefined,10];
// console.log(a,b,c) //1 2 10
// const [a,b=2,c] = [1,10];
// console.log(a,b,c) //1 10 undefined
const [a, b = 2, c] = [1];
console.log(a, b, c) //1 2 undefined
}
</script>
三、数组的属性与方法
1、数组属性(3)
Array.constructor: 返回创建数组对象的原型函数
Array.length: 设置或返回数组元素的个数
Array.prototype: 通过数组的原型对象可以为所有数组对象添加属性
<script>
let arr = [1,2,3];
console.log(
arr.constructor, //ƒ Array() { [native code] }
arr.length, //3
)
if(!Array.prototype.first){
Array.prototype.frist=function(){
console.log('如果js本身不提供first方法,添加一个返回数组的每一个元素的新方法');
return this[0];
}
}
</script>
2、数组方法(22)
toString(): 返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。注意,这里与不使用任何参数调用jion()方法返回的字符串是一样的。
语法:数组.toString()
<script>
console.log(
[1, 2, 3].toString(),
['a', 'b', 'c'].toString(),
[1, [2, 'C']].toString()
); //1,2,3 a,b,c 1,2,C
</script>
toLocaleString(): 是toString()方法的本地化版本,它调用元素的toLocaleString()方法将每个数组元素转化为字符串。经常返回与toString()方法相同的值,但也完全一样
<script>
var arr1 = {
toLocaleString: function () {
return 'davina';
},
toString: function () {
return 'davina';
}
};
var arr2 = {
toLocaleString: function () {
return 'amy';
},
toString: function () {
return 'amy';
}
};
var arr = [arr1, arr2];
console.log(arr.toString()); //davina amy
console.log(arr.toLocaleString()); //davina amy
//如果数组中的某一项的值是null或者是undefined,则用上面两个方法的时候,返回的结果以空字符串表示
var color = ['red', , 'pink', undefined, null];
console.log(color.toString()); //red,,pink,,
console.log(color.toLocaleString());//red,,pink,,
</script>
valueOf(): 返回数组对象本身
<script>
var arr = [1, 2, 3];
console.log(arr.valueOf()); //(3) [1, 2, 3]
</script>
join(): Array.join()方法将数组中所有元素都转化为字符串并连接在一起,返回最后生成的那个字符串,可以指定一个可选的字符串在生成的字符串中来分隔数组的各个元素,如果不进行指定的话那就默认使用逗号。
<script>
var arr = ['d', 'a', 'v', 'i', 'n', 'a'];
console.log(arr.join()); //d,a,v,i,n,a
console.log(arr.join("")) //davina
console.log(arr.join('-')) //d-a-v-i-n-a
////如果数组中的某一项的值是null或者是undefined,用这个方法的时候,返回的结果以空字符串表示
var a = [1, 2, , undefined, 3, null, 4];
console.log(a.join()) //1,2,,,3,,4
//这个方法也可以用在有length属性的数组对象上
console.log(Array.prototype.join.call('davina', '-')); //d-a-v-i-n-a
//使用这个方法可以创建重复某些字符N次的函数
function repeatString(str, n) {
return new Array(n + 1).join(str);
}
console.log(repeatString('a', 3)); //aaa
console.log(repeatString('dvaina', 5));//dvainadvainadvainadvainadvaina
</script>
push(): 此方法可以接收任意数量的参数,把它们逐个添加到数组的末尾且返回修改后数组的长度。会改变原数组
语法:数组.push(element1,element2.......) 返回值:返回数组添加后的长度。
<script>
var color = ['red', 'pink', 'white'];
var color1 = ['purple'];
console.log(color.push('green'), color); //(4) ["red", "pink", "white", "green"]
//可以使用apply()方法将两个数组合并
console.log(color, Array.prototype.push.apply(color, color1)); // ["red", "pink", "white", "green", "purple"] 5
//如果用call()方法,则把color1整体看成一个参数
console.log(color, Array.prototype.push.call(color, color1)); //(6) ["red", "pink", "white", "green", "purple", Array(1)] 6
//它可以以向对象中添加元素,添加后的对象变成类数组对象,即新加入元素的键对应数组的索引,并且对象有一个length属性
var obj = {
a: 1
}
console.log(obj, [].push.call(obj, 3)); //{0: 3, a: 1, length: 1} 1
console.log(obj,[].push.call(obj, [5])); //{0: 3, 1: Array(1), a: 1, length: 2} 2
</script>
pop(): 此方法是从数组末尾移除最后一项,减少数组的length值,然后返回移除的项,会改变原数组,变成删除后的新数组。
语法:数组.pop() 返回值:返回那个被删除的数据
<script>
var color = ['red', 'pink', 'white'];
console.log(color, color.pop()) //(2) ["red", "pink"] "white"
var arr = [];
console.log(arr, arr.pop()); //[] undefined
</script>
shift(): 此方法移除数组中的第一个项且返回该项,同时数组的长度减1,所以原数组会改变,变成删除后的数组
语法:数组.shift() 返回值:返回被删除的那个数据,
<script>
let color = ['red', 'pink', 'white'];
console.log(color, color.shift()); //) ["pink", "white"] "red"
var arr = [];
console.log(arr, arr.pop()); //[] undefined
</script>
unshift():此方法在数组前端添加任意个项且返回新数组的长度,会改变原数组
语法:数组.unshift(element1,element2......) 返回值:返回添加数据后新数组
<script>
var color = ['red', 'pink', 'white'];
console.log(color, color.unshift('green')); //(4) ["green", "red", "pink", "white"] 4
//当使用多个参数调用unshift()时,参数是一次性的插入。这意味着最终的数组中插入的元素的顺序和它们在参数列表中的顺序一致
console.log(color, color.unshift('yellow', 'blank'));//(6) ["yellow", "blank", "green", "red", "pink", "white"] 6
</script>
reverse(): 此方法用于反转数组的顺序,返回经过排序后的数组,而原数组顺序也发生改变
语法:数组.reverse() 返回值:返回反转后的新数组
<script>
var color = ['red', 'pink', 'white'];
console.log(color, color.reverse());
//(3) ["white", "pink", "red"] (3) ["white", "pink", "red"]
</script>
sort(): 默认情况下,sort()方法按字符串升序排列数组项,sort()会调用每个数组项的toString(),然后比较得到字符串排序,返回经过排序后的数组,而原数组顺序也发生变化。
语法:数组.sort() 返回值:返回经过排序后的数组
<script>
// var color = ['a', 4, 3, undefined, 1];
// console.log(color, color.sort()); (5)[1, 3, 4, "a", undefined](5)[1, 3, 4, "a", undefined]
//如果数组包含undefined,它们会被排到最后
//sort()方法可以授受一个比较函数作为参数,以便指定哪个上值在前,哪个值在后。
//如果第一个参数应该位于第二个参数之前则返回一个负数,///如果两个参数相等则返回0
//如果第一个参数应该位于第二个参数之后则返回一个正数
function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 = value2) {
return 0;
} else {
return 1;
}
}
var arr = ['5px', 50, 0, 10];
//字符串与数字相比较时,字符串会被转换成NaN,这样结果是false
console.log(arr.sort(compare)); //(4) ["5px", 0, 10, 50]
//对于数值类型或valueOf()方法会返回数值类型的对象类型,比较函数可以简化
function compare1(value1, value2) {
return value1 - value2;
}
var arr1 = ['5px', 50, 0, 10];
console.log(arr1.sort(compare1));//(4) ["5px", 0, 10, 50]
//如果对一个字符串进行比较,先转化成小写字母进行比较
var arr2 = ['davina', 'Amy', 'PENG'];
console.log(arr2.sort());//(3) ["Amy", "PENG", "davina"]
var c = arr2.sort(function (v1, v2) {
var arr2 = v1.toLocaleLowerCase();
var arr3 = v2.toLocaleLowerCase();
if (arr2 < arr3) return -1;
if (arr2 > arr3) return 1;
return 0;
});
console.log(c);// ["Amy", "davina", "PENG"]
//可以使用sort()创建随机数组(前面已介绍)
</script>
concat():此方法基于当前数组中的所有项创建一个新数组,先创建当前数组的一个副本,然后将然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。不影响原数组。
如果不给concat()方法传递参数时,它只是复制数组,是一个浅拷贝;如果参数是一个或者是多个数组,会将数组中的每一项都添加到结果数组中;如果传递的不是数组,这些值会被简单的传递到结果数组后面。
语法:数组.concat(element1,element2,......) 返回值:返回创建的新数组
<script>
var numbers = [1, 2, 3];
console.log(
numbers.concat(), //[1, 2, 3]
numbers.concat(3, 4), //(5) [1, 2, 3, 3, 4]
numbers.concat([6, 7], [8, 9]), //(7) [1, 2, 3, 6, 7, 8, 9]
numbers.concat(4, [5, [6, 7]]), //(6) [1, 2, 3, 4, 5, Array(2)]
numbers //(3) [1, 2, 3]
)
//此方法也可以用于将对象合并为数组,但是要用到call()方法
var newArray = Array.prototype.concat.call({ a: 1 }, { b: 2 });
console.log(
newArray, //[{a:1},{b:2}]
newArray[0].a, //1
)
</script>
slice(): 返回从原数组中指定开始下标到结束下标之间的项组成的新数组。此方法可以接受一或者两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下,slice()方法返回从该参数指定位置开始到当前数组结束位置的所有项,如果有两个参数,此方法返回起始和结束位置之间的项,不包括结束位置的项。
语法:数组.slice(begin,end) 返回值:返回排序后的数组
<script>
var arr = [1, 2, 3, 4, 5];
console.log(arr.slice(2)); //(3) [3, 4, 5]
console.log(arr.slice(2, 4)); //(2) [3, 4]
console.log(arr.slice(2, undefined)); //(3) [3, 4, 5]
console.log(arr.slice(3, 1)); //[]
//如果start是负数,则start = max(length+start,0)
//如果end是负数,则end = max(length+end,0)
//start和end不能交接位置
console.log(arr.slice(-3)); //(3) [3, 4, 5]
console.log(arr.slice(-2, -1)); // [4] -2+5=3,-1+5=4
//slice()方法涉及到Number()转型函数的隐式类型转换,当start被转换为NaN时,相当于start = 0;当end被转换为NaN时(end为undefined除外),则输出空数组
console.log(arr.slice(NaN)); //(5) [1, 2, 3, 4, 5]
console.log(arr.slice(0, NaN)); //[]
console.log(arr.slice(NaN, 4)); //(4) [1, 2, 3, 4]
console.log(arr.slice(true, [3])); //(2) [2, 3]
//不提供参数,slice()方法返回当前数组的浅拷贝
var numbers = [2, 3, 4];
var newNumbers = numbers.slice();
console.log(numbers, newNumbers) //(3) [2, 3, 4] (3) [2, 3, 4]
numbers[1] = 0;
console.log(numbers, newNumbers) //(3) [2, 0, 4] (3) [2, 3, 4]
//将类数组对象转成真正的数组(见上篇)
</script>
splice(): 此方法用于删除原数组的一部分成员且可以在被删除的位置添加入新的数组成员,它会改变原数组。返回一个由删除元素组成的数组.原数组变化,变成删除后的剩下的内容。
splice()的第一个参数start指定了插入或者删除的起始位置,如果start是负数,则start=max(length+start,0).一个参数也没有的话,返回空数组,原来的数组不变;如果参数为一个数字,代表截取数组,从传的那个数字开始,一直截到最后一位数据;如果参数为二,代表截取数组,从第一个参数开始,截取的个数为第二个参数的值;如果参数为三,代表替换数组,从第一参数开始,找到第二个参数的个数,所找到的内容换成第三个以及第三个以后参数。如果number是负数或NaN或undefined,则number=0,因此不删除元素。
语法:数组.splice(start1,deleatCount,item) 返回值:返回删除的数组
<script>
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// console.log(arr.splice());//[]
// console.log(arr.splice(4));//(5) [5, 6, 7, 8, 9]
// console.log(arr.splice(-5)); //(4) [1, 2, 3, 4]
// console.log(arr.splice(NaN)); //[] 会改变原数组
//第二个参数
// console.log(arr.splice(1, 3)); // (3) [2, 3, 4]
// console.log(arr.splice(5, 3)); //(3) [6, 7, 8]
// console.log(arr.splice(1, -4));//[]
// console.log(arr.splice(3, NaN));//[]
// console.log(arr.splice(1, undefined));//[]
//如果后面还有更多的参数,表示这些就是要被插入数组的新元素
var a = [1, 2, 3];
console.log(a, a.splice(2, 0, 'a', 'b')); //(5) [1, 2, "a", "b", 3] []
console.log(a, a.splice(2, 2, [1, 2], 3)); //(5) [1, 2, Array(2), 3, 3] (2) ["a", "b"]
</script>
indexOf(): 此方法接收search和start两个参数,返回search首次出现的位置,如果没有找到则返回-1,search参数表示要搜索的项,须用严格相等运算符进行比较;start参数表示搜索的开始位置,这个方法会隐式的调用Number()转型函数,将start非数字值(undefined除外)转为数字,若忽略这个参数或者这个参数是undefined或者NaN时,start为0.
语法:数组.indexOf(search,start) 返回值:返回位置
<script>
var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 1, 2, 3];
console.log(arr.indexOf(3)); //10
console.log(arr.indexOf(0));//-1
console.log(arr.indexOf('c', undefined)); //2
console.log(arr.indexOf('d', 8));//-1
console.log(arr.indexOf('b', true)); //1
console.log(arr.indexOf('e', false));//4
console.log(arr.indexOf('b', -2));// -1 max(0,-2+11)=9;
</script>
lastIndexOf():与indexOf()不同,此方法是从右向左查找。lastIndexOf(search,start)方法接收search和start两个参数,返回search第一次出现的位置,如果没有找到则返回-1。
search参数表示要搜索的项;使用严格相等运算符(===)进行比较;start表示该搜索的开始位置,该方法会隐式调用Number()转型函数,将start非数字值(undefined除外)转换为数。若忽略该参数或该参数为undefined或NaN时,start = 0;与字符串的lastIndexOf()方法不同,当search方法为负数时,search = max(0,length+search)
语法:数组.lastIndexOf(search,start) 返回值:返回位置
<script>
var arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 1, 2, 3];
console.log(arr.lastIndexOf('e'));//4
console.log(arr.lastIndexOf(0));//-1
console.log(arr.lastIndexOf('c', undefined)); //-1
console.log(arr.lastIndexOf('d', 8));//3
console.log(arr.lastIndexOf('b', true)); //1
console.log(arr.lastIndexOf('e', false));//-1
console.log(arr.lastIndexOf('b', -2));// 1 max(0,-2+11)=9;
//返回满足条件项的索引
function allIndexOf(array, value) {
var result = [];
var pos = array.indexOf(value);
if (pos === -1) {
return -1
}
while (pos > -1) {
result.push(pos);
pos = array.indexOf(value, pos + 1);
}
return result;
}
var array = [1, 2, 3, 1, 3];
console.log(allIndexOf(array, 1)); //(2) [0, 3]
</script>
rdeuce(): 将数组元素计算为一个值。从左到右处理数组。此方法需要两个参数。每一个参数执行化简操作的函数,用某种方法把两个值组合或化简为一个值且返回化简后的值
化简函数接受四个值:初始变量,默认为数组的第一个元素值,函数第一次执行的返回值作为函数第二次执行的初始变量,依次类推(必须)
当前变量,如果指定了第二个参数,这个变量为数组的第一个元素的值,否则为第二个元素的值(必须)
当前变量对应的元素在数组中的索引(可选)
原数组对象(可选)
在空数组上,不带初始值参数调用reduce,将会报错.如果调用它时只有一个值或者是数组只有一个元素没有指定初始值的情况下,只会简单的返回那个值,不会进行函数的调用
<script>
var arr = [1, 2, 3, 4, 5];
var sum = arr.reduce(function (prev, cur) {
return prev + cur //数组求和
}, 0)
var pro = arr.reduce(function (prev, cur) {
return prev * cur //数组相乘
}, 1)
var max = arr.reduce(function (prev, cur) {
return (prev > cur) ? prev : cur; //比较大小
})
console.log(sum, pro, max); //15 120 5
//由于reduce()方法依次处理每个元素,所以实际上还可以用它来搜索某个元素
function find(entries) {
return entries.reduce(function (prev, cur) {
return cur.length > prev.length ? cur : prev;
}, '')
}
console.log(find([1, 2, 3, 'ab', 'ac', 5, 23])); //ab
//在空数组,调用只有一个元素,数组只有一个元素,调用无元素
var array = [];
var array1 = [1];
// console.log(array.reduce(function(){})); //报错
console.log(array1.reduce(function () { })); //1
console.log(function () { }, 1); // 1
</script>
reduceRight():和reduce()一样,不同点在于它按照数组索引从右到左,处理数组。
<script>
var arr = [1, 2, 3, 4, 5];
var sum = arr.reduceRight(function (prev, cur) {
return prev + cur //数组求和
}, 0)
var pro = arr.reduceRight(function (prev, cur) {
return prev * cur //数组相乘
}, 1)
var max = arr.reduceRight(function (prev, cur) {
return (prev > cur) ? prev : cur; //比较大小
})
console.log(sum, pro, max); //15 120 5
//由于reduce()方法依次处理每个元素,所以实际上还可以用它来搜索某个元素
function find(entries) {
return entries.reduceRight(function (prev, cur) {
return cur.length > prev.length ? cur : prev;
}, '')
}
console.log(find([1, 2, 3, 'abC', 'ac', 5, 23])); //abC
//在空数组,调用只有一个元素,数组只有一个元素,调用无元素
var array = [];
var array1 = [1];
// console.log(array.reduceRight(function(){})); //报错
console.log(array1.reduceRight(function () { })); //1
console.log(function () { }, 1); // 1
</script>
map(): 通过指定函数处理数组的每个元素,并返回处理后的数组。这个方法还可以接受第二个参数,表示回调函数执行时this所指向的对象。在实际使用的时候,可以利用map()方法方便地获得对象数组中特定属性值。
<script>
var arr = [2, 3, 4, 55, 3, 2, 5];
function double(num) {
return num * 2
}
console.log(arr.map(double)); //(7) [4, 6, 8, 110, 6, 4, 10]
//获取对象数组中特定属性值
var arr1 = [
{ name: 'davina', email: 'davina@qq.com' },
{ name: 'Amy', email: 'Amy@qq.com' },
{ name: 'sily', email: 'sily@qq.com' }
]
console.log(arr1.map(function (item, index, arr) {
return item.email; //(3) ["davina@qq.com", "Amy@qq.com", "sily@qq.com"]
}))
</script>
forEach():对数组中的每一项运行给定函数,这个方法没有返回值。本质上与for循环迭代数组一样,如果需要有返回值,一般使用的是map()方法
<script>
var arr = [1, 2, 3, 4];
arr.forEach(function (item, idex, arr) {
console.log(item);
})
//1
//2
//3
//4
for (var i = 0, length = arr.length; i < length; i++) {
console.log(arr[i]);
}
//以上两个实现同一个效果
var sum = 0;
arr.forEach(function (item, idex, arr) {
sum += item;
})
console.log(sum) //10
//forEach()方法除了接受一个必须的回调函数参数,第二个参数还可以接受一个可选的上下文参数(改变this指向)
var obj = {
name: 'davina',
times: [1, 2, 3],
age: 18,
print: function () {
//this指向obj
console.log(this);
this.times.forEach(function (n) {
//this指向window
console.log(this)
});
}
}
obj.print();
//forEach()须放入一个try块中,才能说是像for循环中的break那样中止
for (var i = 0; i < 5; i++) {
if (i == 2) break;
}
console.log(i); //2
var a = [1, 2, 3, 4, 5];
a.forEach(function (item, index, arr) {
try {
if (item == 2) throw new Error;
} catch (e) {
console.log(item); //2
}
})
</script>
filter(): 对数组中的每一项运行给定函数,这个函数会返回true的项组成的数组,该方法常用于查询符合条件的所有数组项。它也可以接收第二个参数,指定this对象。它会跳过稀疏数组中少的元素,返回数组总是稠密的,所以可以利用这一点来压缩空缺并删除undefined和null元素。
<script>
var arr = [1, 2, 3, 4, 5];
var obj = function () {
this.max = 3;
}
var myFilter = function (item) {
if (item > this.max) {
return true
}
}
console.log(arr.filter(myFilter, new obj())); //(2) [4, 5]
var arr1 = [2, 3, undefined, null, , 6, 9];
console.log(arr1.length);//7
var dense = arr1.filter(function (item) {
return item != undefined
})
console.log(dense, dense.length); //(4) [2, 3, 6, 9] 4
</script>
some(): 对数组中的每一项运行给定函数,如果该函数对对任一项返回true,则返回true。并且当且仅当数值中的所有元素调用判定函数都返回false,它才返回false。在空数组上调用此方法会返回false.
<script>
function big(element, index, array) {
return element > 10;
}
var a = [1, 2, 34, 34, 21, 4];
console.log(a.some(big));//true
</script>
every(): 此方法对数组中的每一项运行给定函数,如果函数对每一项都返回true,才是true,否则返回false.
<script>
function big(element, index, array) {
return element > 10;
}
var a = [1, 2, 34, 34, 21, 4];
console.log(a.every(big));//false
</script>