今天对数组进行深刻的了解,不能只停留在会使用的阶段,要知道,它是为什么来的。
数组的分类
1 . 稀疏数组
数组两个值之间可以有空隙,数组也是一个特殊的对象,有着相应的键值,对应的键值不存在,也是可以的。
当进行遍历时,则没有元素:
var a = [10,2];
a[4] = 4;
console.log(a);
a.forEach(function(item,index,O){
console.log(item)
},[1,2,3])
结果如下:
之前当学习的稀疏数组的时候,如果中间没有值得话,还显示undefined,浏览器更新了之后,就变成empty了。
2 . 密集数组
从字面意思理解,就是数组的两个值之间没有空隙。
var a = [1,2,3,4,5];
console.log(a);
a.forEach(function(item,index,O){
console.log(item)
},[1,2,3])
3 . 数组属性
- length
var a = [1,2,3,4];
a.length = 6;//=>[1,2,3,4,empty,empty]
a.length = 2;//=>[1,2]
//键值也是可以改变的
a[1] = 10;//=><10,2,3,4>
prototype
返回对象类型原型的引用,上一篇也用过这个方法,直接在原型链上编辑方法。
forexample:
Array.prototype.min = function(){
var min = this[0];
for(var i = 1;i < this.length;i++){
min = min > this[i]?this[i]:min;
}
return min;
}
a.min();//=>1
这个一般是给数组添加新的方法而使用的。
数组的方法
1 . indexOf(searchElement, fromIndex)
var a = [2, 9, 9];
a.indexOf(2); // 0
a.indexOf(7); // -1
The indexOf() method returns the first index at which a given element can be found in the array, or -1 if it is not present.(里面传的第一个数值,在这个数组里面如果有的话,就会返回这个的索引值,如果没有的话,那么就返回-1)
var array = [2, 9, 9, 9, 5];
array.indexOf(5); // 4
array.indexOf(7); // -1
array.indexOf(9, 2); // 2
array.indexOf(2, -1); // -1
array.indexOf(2, -5); // 0
当有两个参数的时候,同样的是,第一个参数不在这个数组里面的时候,指定返回-1,若在这个数组里面的时候,还需要看后面的参数是正还是负,如果是负的话,这时候需要加上数组的length,寻找以后的数。如果是正的话,同样也是寻找以后的数,那么为什么会这样的,接下来分析一下源码:
Array.prototype.indexOf = function(searchElement, fromIndex) {
var k;
if (this == null) {//兼容一下这个数组,别传了null
throw new TypeError('"this" is null or not defined');
}
var o = Object(this);//将数组转化成类数组
var len = o.length ;
if (len === 0) {//如果是空数组,就返回 -1
return -1;
}
var n = fromIndex | 0;//第二个formIndex,如果传值,就用传的值,如果没有的话,就默认为0
if (n >= len) {//如果传的值大于本身的length,就会返回 -1
return -1;
}
k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);//无论传正值还是负值,都会被兼容。
while (k < len) {//循环进行查找这个数的索引
if (k in o && o[k] === searchElement) {
return k;
}
k++;
}
return -1;
};
2 . lastIndexOf(searchElement, fromIndex)
var numbers = [2, 5, 9, 2];
numbers.lastIndexOf(2); // 3
numbers.lastIndexOf(7); // -1
numbers.lastIndexOf(2, 3); // 3
numbers.lastIndexOf(2, 2); // 0
numbers.lastIndexOf(2, -2); // 0
numbers.lastIndexOf(2, -1); // 3
和indexOf(searchElement, fromIndex)的用法刚好相反,理解可以根据前面的进行理解。
3 . push()(改变原数组)
将一个元素或者多个元素添加到数组之后。
var numbers = [1, 2, 3];
numbers.push(4);
console.log(numbers); // [1, 2, 3, 4]
numbers.push(5, 6, 7);
console.log(numbers); // [1, 2, 3, 4, 5, 6, 7]
4 . unshift()(改变原数组)
从数组的前面加上一个或者多个元素。
var a = [1, 2, 3];
a.unshift(4, 5);
console.log(a); // [4, 5, 1, 2, 3]
5 . contact()(不改变原数组)
var arr1 = ['a', 'b', 'c'];
var arr2 = ['d', 'e', 'f'];
var arr3 = arr1.concat(arr2);
// arr3 is a new array [ "a", "b", "c", "d", "e", "f" ]
6 . pop()(改变原数组)
将原数组改变,返回的是删除掉的数值。
var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var popped = myFish.pop();
console.log(myFish); // ['angel', 'clown', 'mandarin' ]
console.log(popped); // 'sturgeon'
7 . shift()(改变原数组)
把数组中的第一位删除,并返回删除的数值。
var a = [1, 2, 3];
var b = a.shift();
console.log(a); // [2, 3]
console.log(b); // 1
8 . slice(start,end)(不改变原数组)
返回从start开始切,一直切到end之前。切的长度是end-start。
var a = [1,2,3,4,5]
var b = a.slice(2);
var c = a.slice(2,4);
a==>[1,2,3,4,5]
b==>[3,4,5]
c==>[3,4]
用这个只是剪切的功能。
9 . splice(a,b, index0 ……)(改变原数组)
从第a位开始切,切b位下来。然后再从断口开始添加。
var a = [1,2,3,4];
a.splice(2,0,5);//=>[1,2,5,3,4]
a.splice(2,1);=>[1,2,3,4]
var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(2, 0, 'drum');
// myFish is ["angel", "clown", "drum", //"mandarin", "sturgeon"]
// removed is [], no elements removed
10 . reverse()(改变原数组)
var a = ['one', 'two', 'three'];
a.reverse();
console.log(a); // ['three', 'two', 'one']
11 . join()(改变原数组)
var a = ['Wind', 'Rain', 'Fire'];
a.join(); // 'Wind,Rain,Fire'
a.join(', '); // 'Wind, Rain, Fire'
a.join(' + '); // 'Wind + Rain + Fire'
a.join(''); // 'WindRainFire'
12 . every(function(item,index,array(原始数组)){ return item>10})
function isBigEnough(element, index, array) {
return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough); // false
[12, 54, 18, 130, 44].every(isBigEnough); // true
这个遍历不一定要遍历完,只是遍历到不满足回调函数的return a > b;只要一个不满足的,断点就在那里。最终返回false,之后全满足是,才会返回true。
它的源码:
Array.prototype.Every = function(callback,thisArg){
if(this == null){
throw new TypeError('this is null is not defined')
}
if(typeof callback != "function"){
throw new TypeError();
}
if(arguments.length>1){
var T = thisArg;
}
var o = Object(this);
var k = 0;
while(k<this.length){
if(k in o){
var kValue = o[k];
var testValue = callback.call(T,kValue,k,o);
if(!testValue){
return false;
}
k++;
}
}
return true;
}
12 . some(function(item,index,array(原始数组)){return item>10})
若回调函数中找到一个返回true时,则立即返回true,全返回false时,才返回false。
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
源码,就是相反的。
13 . forEach(function(item,index,array(原始数组)){})
const arr = ['a', 'b', 'c'];
arr.forEach(function(element) {
console.log(element);
});
// a
// b
// c
源码:
Array.prototype.q = function(callback/*, thisArg*/) {
var T, k;
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
var len = O.length;
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
if (arguments.length > 1) {
T = arguments[1];
}
k = 0;
while (k < len) {
var kValue;
if (k in O) {
kValue = O[k];
callback.call(T, kValue, k, O);
// callback(kValue, k, O);
}
k++;
}
};