JavaScript 整理笔记之数组详解

JavaScript 数据类型之数组 Array

1.定义

Array 对象用于在单个的变量中存储多个值。
typeof [] === 'object'; // true
Object.keys([1, 3, 5, 7]); // [0, 1, 2, 3] 返回数组对象的key值数组

2.创建方法

var arr1 = new Array(); // []
var arr2 = new Array(3); // [undefined x 3]
var arr3 = new Array(1, 2, 3); // [1, 2, 3]
var arr4 = []; // []

3.属性

length属性 - 设置或返回数组中元素的数目。

arr1.length; // 0
arr2.length; // 0
arr3.length; // 3
arr4.length; // 0
JavaScript语言规定,对象的键名一律为字符串,所以,数组的键名其实也是字符串。之所以可以用数值读取,是因为非字符串的键名会被转为字符串。
arr3["1"]; // 2
arr3[1]; // 2
length属性是可写的。如果人为设置一个小于当前成员个数的值,该数组的成员会自动减少到length设置的值。
arr3.length = 2;
arr3; // [1, 2]

constructor属性 - 返回对创建此对象的数组函数的引用。

arr1.constructor; // ƒ Array() { [native code] }

prototype属性 - 使您有能力向对象添加属性和方法。

Array.prototype.empty = function(){
	return [];
};
[1, 2, 3, 4].empty(); // []

4.类似数组的对象

函数的arguments对象

function args() { 
	return arguments; 
}
var arrayLike = args('a', 'b');
arrayLike[0]; // 'a'
arrayLike.length; // 2
arrayLike instanceof Array; // false

大多数DOM元素集

var elts = document.getElementsByTagName('h3');
elts.length; // 3
elts instanceof Array; // false

字符串

'abc'[1]; // 'b'
'abc'.length; // 3
'abc' instanceof Array; // false

5.方法

Array.isArray() - 该方法判断是否是数组

var arr = [];
Array.isArray(arr); // true

valueOf() - 该方法返回数组本身。

var arr = [1, 2, 3];
arr.valueOf(); // [1, 2, 3]

toString() - 该方法返回数组的字符串形式。

var arr = [1, 2, 3];
arr.toString(); // '1,2,3'

push() - 该方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。

var arr = [1, 2, 3];
arr.push(5); // 4
arr; // [1, 2, 3, 5]
arr.push(4, 5); // 6
arr; // [1, 2, 3, 5, 4, 5]
如果需要合并两个数组,可以这样写。
var arr2 = [5, 6, 7];
arr.push.apply(arr, arr2); // 9 此时返回的是数组改变后的长度
arr; // [1, 2, 3, 5, 4, 5, 5, 6, 7]
push方法还可以用于向对象添加元素,添加后的对象变成类似数组的对象,即新加入元素的键对应数组的索引,并且对象有一个length属性。
var obj = { a: 1 };
[].push.call(obj, 1); // 1 
obj; // {a: 1, 0: 1, length: 1}
[].push.call(obj, 2); // 2
obj; // {a: 1, 0: 1, 1: 2, length: 2}

pop() - 该方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组。

var arr = [1, 3, 5];
arr.pop(); // 5
arr; // [1, 3]
对空数组使用pop方法,不会报错,而是返回undefined。
[].pop(); // undefined

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

var arr = ['j', 'o', 'i', 'n'];
arr.join(); // 'j,o,i,n'
arr.join(''); // 'join'
如果数组成员是undefined或null或空位,会被转成空字符串。
var arr = [undefined, null, , ''];
arr.jooin('#'); // ###
通过call方法,这个方法也可以用于字符串。
Array.prototype.join.call("hello", "-"); // 'h-e-l-l-o'
join方法也可以用于类似数组的对象。
Array.prototype.join.call(arrayLike, "-"); // 'a-b'

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

var arr = [1, 3];
arr.concat([2,4]); // [1, 3, 2, 4]
arr; // [1, 3]
[1, 2].concat([3, 4], [5, 6]); // [1,2,3,4,5,6]
除了接受数组作为参数,concat也可以接受其他类型的值作为参数。它们会作为新的元素,添加数组尾部。
[1, 2].concat(4, 5, 6); // [1, 2, 4, 5, 6]
concat方法也可以用于将对象合并为数组,但是必须借助call方法。
[].concat.call({ 1: 2 }, { 2: 3 }); // [{1;2},{2:3}]
[2].concat({ 1: 2 }); // [2,{1;2}]
[].concat.call({ 1: 2 }, [2]); // [{1;2},2]

shift() - 该方法用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组。

var arr = [1, 3];
arr.shift(); // 1
arr; // [3]
[].shift(); // undefined

unshift() - 该方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。

var arr = [2, 3, 4, 5];
arr.unshift(1); // 5
arr; // [1, 2, 3, 4, 5]

reverse() - 方法用于颠倒数组中元素的顺序,返回改变后的数组。注意,该方法将改变原数组。

var arr = [1, 3, 5];
arr.reverse(); // [5, 3, 1]

slice() - 该方法用于提取原数组的一部分,返回一个新数组,原数组不变。

var arr = [2, 4, 6, 8, 10];
arr.slice(2); // [6, 8, 10]
arr.slice(0, 1); // [2]
arr.slice(-1); // [10]	相当于 arr.slice(-1 + arr.length) => arr.slice(4)
arr.slice(-3, -1); // [6, 8] 相当于 arr.slice(-3 + arr.length, -1 + arr.length) => arr.slice(2, 4)
arr; //  [2, 4, 6, 8, 10]
slice方法的一个重要应用,是将类似数组的对象转为真正的数组。
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 }); // ['a', 'b']
Array.prototype.slice.call(document.querySelectorAll("div")); // [div, div, div]
function args2(){
	return Array.prototype.slice.call(arguments);
}
args2(1, 2, 3); // [1, 2, 3]

splice() - 该方法用于删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。 splice的第一个参数是删除的起始位置,第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.splice(8); // [9]
arr; // [1, 2, 3, 4, 5, 6, 7, 8]
arr.splice(5, 2); // [6, 7]
arr; // [1, 2, 3, 4, 5, 8]
arr.splice(-2, 2, 1, 2, 3); // [5, 8]
arr; // [1, 2, 3, 4, 1, 2, 3]

sort() - 方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。

var arr = [5, 2, 3];
arr.sort(); // [2, 3, 5]
arr; // [2, 3, 5]
sort方法不是按照大小排序,而是按照对应字符串的字典顺序排序。也就是说,数值会被先转成字符串,再按照字典顺序进行比较,所以101排在11的前面。
[101, 11].sort(); // [101, 11]
[101, 11].sort(function(a, b){
	return a - b;
}); // [11, 101]
[101, 11].sort(function(a, b){
	return a - b <= 0;
}); // [101, 11]

map() - 该方法对数组的所有成员依次调用一个函数,根据函数结果返回一个新数组, 原数组没有变化。

 var arr = [1, 3, 5];
 arr.map(function(v) {
    return v * v;
}); // [1, 9, 25]
arr; // [1, 3, 5]
map方法接受一个函数作为参数。该函数调用时,map方法会将其传入三个参数,分别是当前成员、当前位置和数组本身。
 arr.map(function(value, index, arr) {
    return index;
}); // [0, 1, 2]
map方法不仅可以用于数组,还可以用于字符串,用来遍历字符串的每个字符。但是,不能直接使用,而要通过函数的call方法间接使用,或者先将字符串转为数组,然后使用。
Array.prototype.map.call("hello", (function(v) {
    return v.toUpperCase();
})); // ["H", "E", "L", "L", "O"]
map方法还可以接受第二个参数,表示回调函数执行时this所指向的对象。
var arr = [5, 6, 7, 8];
[1, 2, 3].map(function(v) {
    return this[v];
}, arr); // [6, 7, 8]
如果数组有空位,map方法的回调函数在这个位置不会执行,会跳过数组的空位, undefined和null不会跳过。
var f = function(n) { return n + 1 };
[1, undefined, 3].map(f); // [2, NaN, 4]
[1, null, 3].map(f); // [2, 1, 4]
[1, , 3].map(f); // [2, , 4]

forEach() - 该方法与map方法很相似,也是遍历数组的所有成员,执行某种操作,但是forEach方法一般不返回值,只用来操作数据。如果需要有返回值,一般使用map方法。forEach方法的参数与map方法一致,也是一个函数,数组的所有成员会依次执行该函数。它接受三个参数,分别是当前位置的值、当前位置的编号和整个数组。

[1, 2, 3].forEach(function(value, index, arr) {
    console.log("[" + index + "] = " + value);
}); 
// [0] = 1 [1] = 2 [2] = 3 
forEach方法也可以接受第二个参数,用来绑定回调函数的this关键字。
var arr = [];
[1, 2, 3, 4].forEach(function(v) {
    this.push(v * v);
}, arr);
arr; // [1, 4, 9, 16]
固定this
var obj2 = {
    0: 1,
    1: 2,
    name: ["stafan", "cindy", "xichen"],
    index: [1, 2, 3],
    print: function() {
        this.index.forEach(function(v) {
            console.log("thisName => ", this.name[v - 1]);
        }, this); // this 指向 obj2
    }
}
obj2.print(); // "thisName => stafan"    "thisName => cindy"   "thisName => xichen"
注意,forEach方法无法中断执行,总是会将所有成员遍历完。如果希望符合某种条件时,就中断遍历,要使用for循环。forEach方法会跳过数组的空位。
function log(n) {
    console.log(n + 1);
}
[1, undefined, 2].forEach(log); // 2,NaN,3
[1, null, 2].forEach(log); // 2,1,3
[1, , 2].forEach(log); // 2,3
forEach方法也可以用于类似数组的对象和字符串。
var obj3 = {
    0: 1,
    1.: 2,
    length: 2
}
Array.prototype.forEach.call(obj3, function(value, index, arr) {
    console.log(index + ':' + value);
}); // 0:1  1:2
var str2 = 'hello';
Array.prototype.forEach.call(str2, function(value, index, arr) {
    console.log(index + ':' + value);
}); // 0:h 1:e 2:l 3:l 4:o

filter() - 该方法的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.filter(function(value, index, arr) {
    return value % 2 === 0;
})); // [2, 4, 6, 8]
arr; // [1,2,3,4,5,6,7,8,9]
filter方法还可以接受第二个参数,指定测试函数所在的上下文对象(即this对象)
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.filter(function(value, index, arr) {
    return this.MAX > value;
}, {  MAX: 3 }); // [1, 2]

some() - 该方法是只要有一个数组成员的返回值是true,则整个some方法的返回值就是true,否则false。

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.some(function(value, index, arr){
	return value > 8;
}); // true
[3, 4, 5].some(function(value, index, arr) {
    return value > 5;
}); // false

every() - 该方法则是所有数组成员的返回值都是true,才返回true,否则false。

[3, 4, 5].every(function(value, index, arr) {
    return value > 2;
}); // true
[3, 4, 5].every(function(value, index, arr) {
    return value > 4;
}); // false
注意,对于空数组,some方法返回false,every方法返回true,回调函数都不会执行。
[].some(log); // false
[].every(log); // true

reduce方法和reduceRight方法依次处理数组的每个成员,最终累计为一个值。

它们的差别是, reduce是从左到右处理( 从第一个成员到最后一个成员), reduceRight则是从右到左( 从最后一个成员到第一个成员), 其他完全一样。
 这两个方法的第一个参数都是一个函数。 该函数接受以下四个参数。
累积变量, 默认为数组的第一个成员
当前变量, 默认为数组的第二个成员
当前位置( 从0开始)
原数组
这四个参数之中, 只有前两个是必须的, 后两个则是可选的。
[1, 2, 3, 4, 5].reduce(function(x, y, i, arr) {
    return x + y;
}); // 15
如果要对累积变量指定初值,可以把它放在reduce方法和reduceRight方法的第二个参数。
[1, 2, 3, 4, 5].reduce(function(x, y, i, arr) {
    console.log(x, y, i, arr);
    return x + y;
}, 10); // 25 第二个参参数相当于指定 x 的初始值
由于空数组取不到初始值,reduce方法会报错。这时,加上第二个参数,就能保证总是会返回一个值。
var sum = function(x, y) {
    return x + y;
};
[].reduce(sum, 0); // 0
[].reduce(sum); // TypeError: Reduce of empty array with no initial value 
var subtract = function(x, y) {
    return x - y;
}
[3, 2, 1].reduce(subtract); // 0
[3, 2, 1].reduceRight(subtract); // -4
reduce 变相找出长度最长的元素
function findLongest(entries) {
    return entries.reduce(function(x, y, i, arr) {
        return x.length > y.length ? x : y;
    }, '');
}
findLongest(['ss', 'abc', 'stafan', 'cindy']); // stafan

indexOf() - 该方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。

[1, 2, 3].indexOf(3); // 2
[1, 2, 3].indexOf(4); // -1

lastIndexOf() - 该方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回-1。

[1, 2, 3, 1].lastIndexOf(1); // 3
[1, 2, 3, 1].lastIndexOf(4); // -1
// 注意,如果数组中包含NaN,这两个方法不适用,即无法确定数组成员是否包含NaN。
[NaN].indexOf(NaN); // -1
[NaN].lastIndexOf(NaN); // -1
上面这些数组方法之中,有不少返回的还是数组,所以可以链式使用。
var users = [
    { name: 'tom', email: '[email protected]' },
    { name: 'peter', email: '[email protected]' },
    { name: 'peter', email: '[email protected]' },
];
users
    .map(function(user) {
        return user.email;
    })
    .filter(function(email) {
        return /^t/.test(email);
    })
    .forEach(function(v){
        console.log(v);
    });

猜你喜欢

转载自blog.csdn.net/Ama_zhe/article/details/86063946