数组 Array数组
本质上,数组属于一种特殊的对象。typeof
运算符会返回数组的类型是 object
函数
// Object.keys方法返回数组的全部键名。 var arr = ['a', 'b', 'c']; Object.keys(arr); // ["0", "1", "2"] // 能够看到数组的键名就是整数0、一、2。
length
属性的最大值就是 4294967295与普通对象的区别是 "数组使用数字做为索引 [index] 来操做属性"。index 从 0 开始。性能
数组的存储性能相对较好。this
var arr = ['唐僧','孙悟空','猪八戒','沙和尚','白龙马'];spa
1. 建立数组对象prototype
var arr = new Array(); // typeof arr 返回 object
2. 给数组添加对象code
arr[0] = 1; // console.log(arr) 打印 "1" arr[1] = 11; // console.log(arr) 打印 "1,11" arr[2] = 22; // console.log(arr) 打印 "1,11,22"
3. 读取数组对象对象
console.log(arr[0]); // 1 console.log(arr[1]); // 11 console.log(arr[2]); // 22 console.log(arr[3]); // undefined 不会报错
4. 获取数组长度blog
var arr = [1,2,3]; console.log(arr.length); // 返回 3 ,由于有 3 个元素 arr[0],arr[1],arr[2] arr.[100] = 100; // 此时数组有4个元素 arr[0],arr[1],arr[2],arr[100] console.log(arr.length); // 可是会返回 101 , 实际只有 4 个元素, 这四个元素之外的其余 97 个元素值都为 undefined, 且用 in 判断时返回 false
var arr = [ 'a', 'b', 'c' ]; arr.length = 0; arr // []
5. 在数组最后添加元素排序
// 根据上一个特性,能够在数组最后追加一个元素 arr[arr.length] = 666;
1. 使用字面量来建立数组
var arr = []; // 和 new Array() 效果相同
2. 在建立时指定元素
var arr = [0,1,2,3,4]; // 等同于 var arr = new Array(0,1,2,3,4);
3. 建立一个只有一个元素的数组
var arr = [10]; // 此时数组只有1个元素,arr[0] = 10; var arr = new Array(10); // 此时建立了一个长度为10的数组!!! // 每一个元素的值都为 undefined
4. 数组中元素能够听任意数据类型的数据
var arr = ["Hello","How",1,2,3,null,undefined,true,false]; // 数组元素是对象 var sun = {name:"孙悟空"}; arr[arr.length] = sun; console.log(arr[arr.length-1].name); // 将会打印 "孙悟空" // 数组元素是函数 var arr = [ function(){console.log("Hello!"}, function(){console.log("Hi!")} ]; // 数组 里面放 数组 var newArr = [["01","02","03"],[0,1,2],["11","22","33"]]; // 混合着放 var arr = [ {a: 1}, // 对象 [1, 2, 3], // 数组 function() {return true;} // 函数 ]; arr[0] // Object {a: 1} arr[1] // [1, 2, 3] arr[2] // function (){return true;}
5. 遍历数组
for...in
循环不只能够遍历对象,也能够遍历数组,毕竟数组只是一种特殊对象
var a = [1, 2, 3]; for (var i in a) { console.log(a[i]); // 1 2 3 }
for...in
不只会遍历数组全部的数字键,还会遍历非数字键。因此,不推荐使用 for...in
遍历数组。
var a = [1, 2, 3]; a.foo = true; for (var key in a) { console.log(key); // 0 1 2 foo console.log(key); // 1 2 3 true }
for
循环 或 while
循环
var a = [1, 2, 3]; // for循环 for(var i = 0; i < a.length; i++) { console.log(a[i]); } // while循环 var i = 0; while (i < a.length) { console.log(a[i]); i++; } // 逆向遍历 var l = a.length; while (l--) { console.log(a[l]); }
var colors = ['red', 'green', 'blue']; colors.forEach(function (color) { console.log(color); // red green blue });
length
属性
var a = ['a' , , 'c']; a.length // 3
// 数组的空位是能够读取的,返回a[1] // undefined
a[2] // 'c'
undefined
a[0] // 'a'
a.length // 3var a = [1, 2, 3,];
length
属性
var a = [1, 2, 3]; delete a[1]; a[1] // undefined a.length // 3
undefined
,是不同的。
forEach
方法、for...in
结构、以及Object.keys
方法进行遍历,空位都会被跳过。
var a = [, , ,]; a.forEach(function (x, i) { console.log(i + '. ' + x); // 不产生任何输出 }) for (var i in a) { console.log(i); // 不产生任何输出 } Object.keys(a) // []
var a = [undefined, undefined, undefined]; a.forEach(function (x, i) { console.log(i + '. ' + x); }); // 0. undefined // 1. undefined // 2. undefined for (var i in a) { console.log(i); // 0 1 2 } Object.keys(a) // ['0', '1', '2']
6. 相似数组对象
length
属性,那么这个对象就很像数组,语法上称为“相似数组的对象”(array-like object)。
var obj = { 0: 'a', 1: 'b', 2: 'c', length: 3 }; obj[0] // 'a' obj[1] // 'b' obj.length // 3 obj.push('d') // TypeError: obj.push is not a function // 由于它们不具有数组特有的方法。 // 对象obj没有数组的push方法,使用该方法就会报错。
length
属性不是动态值,不会随着成员的变化而变化arguments
对象,以及大多数 DOM 元素集,还有字符串。slice
方法能够将 “相似数组的对象” 变成真正的数组
var arr = Array.prototype.slice.call(arrayLike);
call()
,能够把 forEach()
嫁接到 arrayLike
上面调用
arguments
对象上面调用forEach
方法。
// forEach 方法 function logArgs() { Array.prototype.forEach.call(arguments, function (elem, i) { console.log(i + '. ' + elem); }); } // 等同于 for 循环 function logArgs() { for (var i = 0; i < arguments.length; i++) { console.log(i + '. ' + arguments[i]); } }
forEach
要慢,forEach
方法。
var arr = Array.prototype.slice.call('abc'); arr.forEach(function (chr) { console.log(chr); // a b c });
7. 数组的静态方法
var arr = [1, 2, 3]; typeof arr // "object" Array.isArray(arr) // true
8. 数组的实例方法
valueOf
方法 返回数组自己。。。不一样对象的valueOf
方法不尽一致toString
方法 返回数组的字符串形式var arr = []; arr.push(1); // 1 arr.push('a'); // 2 arr.push(true, {}); // 4 // arr = [1, 'a', true, {}]
var arr = ['a', 'b', 'c']; arr.pop() // 'c' // arr = ['a', 'b']
对空数组使用pop
方法,不会报错,而是返回undefined
push
和pop
结合使用,就构成了“后进先出”的栈结构(stack)
shift
方法能够遍历并清空一个数组。
var list = [1, 2, 3, 4, 5, 6]; var item; while (item = list.shift()) { console.log(item); } list // []
push
和shift
结合使用,就构成了“先进先出”的队列结构(queue)
unshift
方法能够接受多个参数,这些参数都会添加到目标数组头部
var a = [1, 2, 3, 4]; a.join(' '); // '1 2 3 4' a.join(' | '); // "1 | 2 | 3 | 4" a.join(); // "1,2,3,4"
[undefined, null].join('#') // '#' ['a',, 'b'].join('-') // 'a--b'
若是数组成员是undefined
或null
或空位,会被转成空字符串
call
方法,这个方法也能够用于字符串或相似数组的对象
Array.prototype.join.call('hello', '-') // "h-e-l-l-o" var obj = { 0: 'a', 1: 'b', length: 2 }; Array.prototype.join.call(obj, '-') // 'a-b'
['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}]
concat
方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用
slice
方法的参数是负数,则表示倒数计算的位置var a = ['a', 'b', 'c']; a.slice(-2); // ["b", "c"] a.slice(-2, -1); // ["b"] var a = ['a', 'b', 'c']; a.slice(4); // [] a.slice(2, 1); // []
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 }) // ['a', 'b'] Array.prototype.slice.call(document.querySelectorAll("div")); Array.prototype.slice.call(arguments);
数值会被先转成字符串,再按照字典顺序进行比较因此101
排在11
的前面
sort
方法按照自定义方式排序,能够传入一个函数做为参数
0
,表示第一个成员排在第二个成员后面;其余状况下,都是第一个元素排在第二个元素前面。
[10111, 1101, 111].sort(function (a, b) { return a - b; }); // [111, 1101, 10111]
[ { 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 } // ]
var numbers = [1, 2, 3]; numbers.map(function (n) { return n + 1; }); // [2, 3, 4] numbers // [1, 2, 3]
map
方法向它传入三个参数:当前成员 elem、当前位置 index、数组自己 arr
[1, 2, 3].map(function(elem, index, arr) { return elem * index; }); // [0, 2, 6]
map
方法还能够接受第二个参数,用来绑定回调函数内部的this
变量
var arr = ['a', 'b', 'c']; [1, 2].map(function (e) { return this[e]; }, arr) // ['b', 'c']
map
方法的回调函数在这个位置不会执行,会跳过数组的空位 (不会跳过不会跳过undefined
和null
)
var f = function (n) { return 'a' }; [1, undefined, 2].map(f); // ["a", "a", "a"] [1, null, 2].map(f); // ["a", "a", "a"] [1, , 2].map(f); // ["a", , "a"]
map
方法很类似,也是对数组的全部成员依次执行参数函数forEach
方法不返回值,只用来操做数据。map
方法,不然使用forEach
方法forEach
方法也能够接受第二个参数,绑定参数函数的 this 变量
forEach
方法也会跳过数组的空位 , 不会跳过undefined
和null
var out = []; [1, 2, 3].forEach(function(elem) { this.push(elem * elem); }, out); out // [1, 4, 9]
forEach
方法没法中断执行,老是会将全部成员遍历完。for
循环
true
的成员组成一个新数组返回。该方法不会改变原数组。
[1, 2, 3, 4, 5].filter(function (elem) { return (elem > 3); }); // [4, 5] 将大于3的数组成员,做为一个新数组返回 var arr = [0, 1, 'a', false]; arr.filter(Boolean); // [1, "a"] 获取全部布尔值为true的成员
[1, 2, 3, 4, 5].filter(function (elem, index, arr) { return index % 2 === 0; }); // [1, 3, 5]
filter
方法还能够接受第二个参数,用来绑定参数函数内部的this
变量
var obj = { MAX: 3 }; var myFilter = function (item) { if (item > this.MAX) return true; }; var arr = [2, 8, 3, 4, 1, 3, 2, 9]; arr.filter(myFilter, obj); // [8, 4, 9]
some
方法是只要一个成员的返回值是true
,则整个some
方法的返回值就是true
,不然返回false
var arr = [1, 2, 3, 4, 5]; arr.some(function (elem, index, arr) { return elem >= 3; }); // true
every
方法是全部成员的返回值都是true
,整个every
方法才返回true
,不然返回false
var arr = [1, 2, 3, 4, 5]; arr.every(function (elem, index, arr) { return elem >= 3; }); // false
some
方法返回false
,every
方法返回true
,回调函数都不会执行
reduce
是从左到右处理(从第一个成员到最后一个成员)reduceRight
则是从右到左(从最后一个成员到第一个成员),其余彻底同样// 求出数组全部成员的和
[1, 2, 3, 4, 5].reduce(function (a, b) { console.log(a, b); return a + b; }); // 1 2 第一次执行, 是数组的第一个成员,是数组的第二个成员 // 3 3 第二次执行, 为上一轮的返回值,为第三个成员 // 6 4 第三次执行, 为上一轮的返回值,为第四个成员 // 10 5 第四次执行, 为上一轮返回值,为第五个成员 // 最后结果:15a1b2a3b3a6b4a10b5
reduce()
和 reduceRight()
的第一个参数都是一个函数。该函数接受如下四个参数
reduce
方法和reduceRight
方法的第二个参数
[1, 2, 3, 4, 5].reduce(function (a, b) { return a + b; }, 10); // 25 // 指定参数a的初值为10,因此数组从10开始累加,最终结果为25。 // 注意,这时b是从数组的第一个成员开始遍历
reduce
方法会报错。这时,加上第二个参数,就能保证老是会返回一个值function substract(prev, cur) { return prev - cur; } // 比较 reduce() reduceRight() [3, 2, 1].reduce(substract) // 0 [3, 2, 1].reduceRight(substract) // -4
function findLongest(entries) { return entries.reduce(function (longest, entry) { return entry.length > longest.length ? entry : longest; }, ''); } findLongest(['aaa', 'bb', 'c']); // "aaa"
-1
var a = ['a', 'b', 'c']; a.indexOf('b'); // 1 a.indexOf('y'); // -1 ['a', 'b', 'c'].indexOf('a', 1); // -1 结果为-1,表示没有搜索到
-1
var a = [2, 5, 9, 2];
a.lastIndexOf(2); // 3
a.lastIndexOf(7); // -1
[NaN].indexOf(NaN) // -1
[NaN].lastIndexOf(NaN) // -1
NaN
的位置,即它们没法肯定数组成员是否包含NaN
var users = [ {name: 'tom', email: 'tom@example.com'}, {name: 'peter', email: 'peter@example.com'} ]; users .map(function (user) { return user.email; }) .filter(function (email) { return /^t/.test(email); }) .forEach(function (email) { console.log(email); }); // 先产生一个全部 Email 地址组成的数组,而后再过滤出以t开头的 Email 地址,最后将它打印出来