[记录] JavaScript 中的数组操作

数组原型:
自定义数组原型函数,给所有数组添加公共方法

Array.prototype.unique = function () {
    var arr = []; // 临时数组 - 存放去重后的数据
    for(var i = 0, len = this.length; i < len; i++){
        // 数组的indexOf有兼容性问题, 未检索到则返回 -1
        if ( arr.indexOf( this[i] ) == -1 ) {
            arr.push( this[i] );
        }
    }
    return arr;
};
var codeArr = [3,1,4,1,5,9,2,6,5,5,5,6,9,1,1,1,3];
console.log( codeArr.unique() );
// [3, 1, 4, 5, 9, 2, 6]

 



A. 定义方式;

   var arr = []; // 数组字面量
   var arr = new Array(); // 数组构造函数


B. 数组的读和写

   arr[num]  // 不可以溢出读  结果undefined
   arr[num] = xxx; // 可以溢出写 

 



改变原数组方法:
1. arr.push()、arr.pop()

arr.push() 方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。
var arr = [];
arr.push(1); // 1
arr.push("A"); // 2
arr.push(true, {}); // 4
console.log( arr ); // ["1", "A", true, {}]


模拟数组方法:

Array.prototype.push = function (){
    for( var i=0;i<arguments.lenght;i++){
        this[this.length] = arguments[i];
    }
    return this.length;
} 


arr.pop() 方法用于删除数组的最后一个元素,并返回该元素。

var arr = ["A", "B", "C"];
arr.pop(); // "C"
console.log( arr ); // ["A", "B"]

// 空数组使用 pop() 方法,不会报错,而是返回 undefined
[].pop(); // undefined


2. arr.shift()、arr.unshift()
arr.shift() 方法用于删除数组的第一个元素,并返回该元素。

var arr = ["A", "B", "C"];
arr.shift(); // "A"
console.log( arr ); // ["B", "C"]


arr.unshift() 方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。

var arr = ["A", "B", "C"];
arr.unshift("H"); // 4
console.log( arr ); // ["H", "A", "B", "C"]
// 添加多个
arr.unshift("Y", "X");
console.log( arr ); // ["Y", "X", "H", "A", "B", "C"]


3. arr.sort([fn]);
arr.sort() 方法对数组成员进行排序,默认是按照字典顺序排序。

["d", "c", "b", "a"].sort();
// ["a", "b", "c", "d"]

[6, 5, 4, 3, 2, 1].sort();
// [1, 2, 3, 4, 5, 6]

[11, 101].sort();
// [101, 11]

[10111, 1101, 111].sort();
// [10111, 1101, 111]
默认排序不是按照大小排序,而是按照字典顺序。
也就是说,数值会被先转成字符串,再按照字典顺序进行比较,所以 101 排在 11 的前面


sort() 自定义方式排序

var arr = [10111, 1101, 111];
arr.sort(function (a, b) {
    // 1. 必须写两个形参,表示进行比较的两个数组成员      
    // 2. 看返回值 
    //    1) 大于 0, 表示第一个排在第二个后面
    //    2) 其他情况, 都是第一个排在第二个前面 
    return a - b;    
});  
// [111, 1101, 10111]


数组中的对象数据:

var arr = [
    { name: "张三", age: 30 },
    { name: "李四", age: 24 },
    { name: "王五", age: 28 }
];
arr.sort(function (a, b) {
    return a.age - b.age;
});
// [
//   { name: "李四", age: 24 },
//   { name: "王五", age: 28 },
//   { name: "张三", age: 30 }
// ]


4. arr.reverse()
用于颠倒排列数组元素,返回改变后的数组

 
var arr = ["A", "B", "C"];
arr.reverse(); 
// ["C", "B", "A"] 


5. arr.splice(从第几位开始, 截取长度, 切口处添加新数据)
用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素

var arr = ["A", "B", "C", "D", "E", "F"];
// 一个参数时: 删除当前位置后面所有元素
arr.splice(2); // ["C", "D", "E", "F"]
// 一个参数时: 负数,表示从倒数位置开始删除
arr.splice(-3); // ["D", "E", "F"]

// 指定删除长度
arr.splice(1, 2); // ["E", "F"]
// 从第一个位置 E 开始删除2个元素
arr.splice(1, 0); // ["E", "F"]
// 截取长度为0是,表示不删除

// 从数组的第一个位置添加两个新元素
arr.splice(1, 0, "A", "B"); // ["E", "A", "B", "F"]
// 从第一个位置删除2个元素,然后添加新元素
arr.splice(1, 2, "V", "V", "M"); // ["E","V","V","M","F"]

 



不改变原数组的方法:
1. arr.concat()
用于多个数组合并。将新添加的成员,添加到原数组成员的后面, 然后返回一个新数组

['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}]

[1,2,3].concat(4,5,6);
// [1, 2, 3, 4, 5, 6]


如果数组成员包括对象, concat 方法返回当前数组的一个浅拷贝。指的是新数组拷贝的是对象的引用。
注意:改变原对象以后,信数组跟着改变。

var oldArr = [{ a: 1}];
var newArr = oldArr.concat();
oldArr[0].a = 10;
console.log( newArr[0].a );


2. arr.join()
指定参数作为分隔符,把数组转成字符串;默认用逗号分隔

var arr = [1, 2, 3, 4];
arr.join(' '); // '1, 2, 3, 4'
arr.join('|'); // '1 | 2 | 3 | 4'
arr.join(); //'1,2,3,4'
// 如果数组成员是undefined或null或空位,会被转成空字符串
[undefined, null].join('#'); // '#'
['A', , 'B'].join('-'); // 'a--b'


3. arr.toString() 返回数组的字符串形式

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

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


4. arr.slice(从该位开始截取, 截取到该位);
用于提取目标数组的一部分,返回一个新数组;

var arr = ['a','b','c'];
// 没有参数,返回原数组的拷贝
arr.slice(); // ['a','b','c']
// 如果省略第二个参数,则一直返回到数组的最后一个成员
arr.slice(0); // ['a','b','c']
arr.slice(1); // ['b','c']
// 包前不包后, 数组的第一位到第二位(不包含第二位)
arr.slice(1, 2); // ['b']
arr.slice(2, 6); // ['c']
// 支持负数,表示倒数计算的位置
arr.slice(-2); // ['b','c']
arr.slice(-2,-1); // ['b']
// 第一个参数大于等于数组的长度
// 或 第二个参数小于第一个参数,则返回空数组
arr.slice(4); // []
arr.slice(2, 1); // []


slice 方法的一个重要应用,是将类数组的对象转为真正的数组。

var arr = { 0: 'a', 1: 'b', length: 2 };
Array.prototype.slice.call(arr);
// ['a', 'b']

Array.prototype.slice.call(document.querySelectorAll('div'));
Array.prototype.slice.call(arguments);

 



#### 类数组
1. 属性要为索引(数字)属性, 必须有length
2. 不具有数组所具有的方法
可以给类数组添加数组方法,如push: Array.prototype.push
如果添加splice方法则就跟数组长一样了 [1, 2, 3]

var obj = {
    "0": 'a',
    "1": 'b',
    "2': 'c',
    "length": 3,
    "push": Array.prototype.push,
    "splice": Array.prototype.splice
}

好处: (类数组push是根据length来替换)
Array.prototype.push = function (target) {
    obj[obj.length] = target;
    obj.length ++;
}

 



数组的其它方法:
arr.map(); // 不改变原数组
把数组的所有成员依次传入参数函数,把每次执行的结果组成一个新数组返回。

var numbers = [1, 2, 3];
numbers.map(function (n) {
    return n + 1;
});
// [2, 3, 4]


函数作为参数调用时, 可以传入三个参数(当前成员, 当前位置, 数组本身)

[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(n) {
    // n 是.map前面数组的每一项, this指向arr数组
    return this[n];
}, arr);
// ['b', 'c']


遇到数组空位,跳过空位,不执行回调

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']


arr.forEach(); 数组遍历
forEach 方法与 map 方法很相似, 对数组所有成员进行遍历。
forEach 方法没有返回值,值用来操作数据。

// 第一个参数是函数,有三个参数:(当前值, 当前位置, 数组本身)
[0, 5, 3].forEach(function(elem, index, arr) {
    console.log('['+index+'] = ' + elem); 
});
// [0] = 0
// [1] = 5
// [2] = 3


可以接受第二个参数,用来绑定回调函数内部的 this 变量

var out = [];
[0, 5, 3].forEach(function(n) {
    this.push(n * n);
}, out);
console.log(out); // [0, 25, 9]


注意:
1. forEach 方法会跳过数组的空位
2. forEach 方法无法中断循环, 总会将所有成员遍历完。
arr.filter(); 过滤数组成员
用于过滤数组成员,满足条件的成员组成一个新数组返回。

第一个参数是回调函数,必填。遍历所有成员,满足条件的成员组成一个新数组返回。

[1,2,3,4,5].filter(function(elem) {
    return (elem > 3);
});
// [4, 5]


返回数组中所有布尔值为 true 的成员

[0, 1, 'a', false, null].filter(Boolean);
// [1, 'a']


回调函数可以接受三个参数: (当前成员,当前位置,数组本身)

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


接受第二个参数,用来改变回调函数中的 this 变量

var obj = { Max: 3 };
var arr = [0, 5, 3, 4, 16];
arr.filter(function(n) {
    // this 指向 obj
    if(n > this.Max) {
        return true;
    }
}, obj);
// [5, 4, 16]


arr.some(fn)、every(fn);
依次遍历数组成员,回调函数接受三个参数: (当前成员,当前位置,数组本身) 返回一个布尔值.
可以接受第二个参数,用来改变回调函数中的 this 变量

some 方法是只要一个满足条件就返回true, 否则返回 false

var arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
    return elem >= 3;
});
// true;


every 方法是全部满足条件才返回true,否则返回 false

var arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
    return elem >= 3;
});
// false;


对于空数组, some 方法返回 false , every 方法返回 true, 回调函数不执行

function isEven(x) {
    return x % 2 === 0;
}
[].some(isEven); // false
[].every(isEven); // true


reduce()、reduceRight() 返回最终的统计结果
reduce 是从左到右处理(第一个到最后一个)
reduceRight 是从右到左处理(最后一个到第一个)
第一个参数是一个回调函数, 接受四个参数
1. 积累变量, 默认第一个成员 (必须)
2. 当前变量, 默认第二个成员 (必须)
3. 当前位置(从0开始)
4. 原数组

[1, 2, 3, 4, 5].reduce(function (a, b) {
    console.log(a, b);
    return a + b;
});
// 1 2
// 3 3
// 6 4
// 10 5
//最后结果:15


第二个参数,指定初始值,在初始值的基础上累加

[1, 2, 3, 4, 5].reduce(function (a, b) {
    console.log(a, b);
    return a + b;
}, 10);
// 25


空数组娶不到初始值,reduce方法会报错。

function add(prev, cur) {
  return prev + cur;
}
[].reduce(add);
// TypeError: Reduce of empty array with no initial value
[].reduce(add, 1); // 默认返回初始值
// 1


arr.indexOf(查找元素, 指定位置)、arr.lastIndexOf(查找元素,指定位置) // IE8不兼容, 会报错
返回给定元素在数组中第一次出现的位置,如果没有找到则返回 -1

var arr  = ["a", "b", "c"];
arr.indexOf("b"); // 1
arr.indexOf("v"); // -1
// 指定搜索的开始位置
arr.indexOf("a", 1); // -1


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

var a = [2, 5, 9, 2];
a.lastIndexOf(2) // 3
a.lastIndexOf(7) // -1


posted @ 2018-08-10 18:03  yuxi2018  阅读(239)  评论(0编辑  收藏  举报