数组API
2020-04-20 本文已影响0人
学的会的前端
join
- MDN定义:
join()
方法将一个数组或类数组对象的所有元素拼接成一个字符串,并且返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。原数组不变。
var a = [1,2,3]
a.join('-') //1-2-3
var b = []
b.join() //'' 无论连接符是什么,都返回空字符串
- 连接类数组对象,
function f (a, b, c) {
var s = Array.prototype.join.call(arguments,'-')
console.log(s)
}
f('a','fank','lili') //a-fank-lili
- 推测类似源代码
Array.prototype.join = function (char) {
let reult = this[i] || 0
let length = this.length
for (let i = 0; i < length; i++){
result += char + this[i]
}
return result
}
slice
- MDN定义:
slice()
方法返回一个新数组对象,这一对象是一个由begin
和end
决定的原始数组的浅拷贝(包括begin
不包括end
),原始数组不会改变。如果向两个数组任一中添加了新元素,则另一个不会受到影响。
var a = [
{ e: 1 },
{ b: 2 },
{c: 3}
]
var b = a.slice(0, 2)
a.e = 5;
console.log(b) // [{e:1},{b:2}]
- 推测类似源代码
Array.prototype.slice = function (begin, end) {
let result = []
begin = begin || 0
end = end || this.length
for (let i = begin; i < end; i++){
result.push(this[i])
}
return result
}
-
slice()
可以用来做伪数组的转化,将伪数组转化成新数组
array = Array.prototype.slice.call(arrayLike) 或者
array = [].slice.call(arrayLike)
- ES6新出的API,专门用来将伪数组转换为真数组
array = array.from(arrayLike)
- 伪数组:原型链中没有
Array.prototype
,只有0,1,2,...length属性,而真数组的亚U型凝练中有Array.prototype
。
sort
- MDN定义:
sort()
方法用原地算法对数组的元素进行排序,并返回数组,原数组被改变。因为,数组原地排序,并不进行复制。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的,由于它取决于具体实现,因此无法保证排序的时间和空间复杂性。
var array = [1, 4, 6, 2, 7, 5]
array.sort((a, b) => a - b)
console.log(array) //[1,2,4,5,6,7]
- 推测类似源代码
Array.prototype.sort = function (fn) {
fn = fn || (a - b) => a - b
let roundCount = this.length - 1
for (let i = 0; i < roundCount; i++){
let minIndex = this[i]
for (let k = i + 1; k < this.length; k++){
if (fn.call(null, this[k], this[i]) < 0) { //决定了k项和i项的前后(大小)关系
[this[i],this[k]] = [this[k],this[i]] //交换二者的值
}
}
}
}
forEach
- MDN定义:
forEach()
方法对数组的每个元素执行一次给定的函数。返回值:undefined,不会改变原数组。
var array = [1, 4, 6, 9];
array.forEach((element, index) => {
console.log(element + "---------" + index);
});
-
forEach()
方法按升序为数组中含有效值的每一项执行一次 callback 函数,那些已删除或者未初始化的项将被跳过
var array = [1, 4, ,6, 9];
array.forEach((element, index) => {
console.log(element + "---------" + index);
});
因为index为2的地方没有初始化数据,所以跳过
-
forEach()
为每个数组元素执行一次callback
函数,与map()
和reduce()
不同的是,它总是返回undefined的值,并且它是不可链式调用的。 - 为了在控制台显示出数组的内容,可以使用
console.table()
来展示经过格式化的数组。 - 如果数组在迭代时被修改了,则其他元素会被跳过。
var array = ["1", "4", "6", "9"];
array.forEach((element, index) => {
console.log(element + "---------" + index);
if (element === "4") {
array.shift();
}
});
/*
1---------0
4---------1
9---------2
*/
--------------------------------------------------------------------------
var array = ["1", "4", "6", "9"];
array.forEach((element, index) => {
if (element === "4") {
array.shift();
} else {
console.log(element + "---------" + index);
}
});
/*
1---------0
9---------2
*/
- 推测类似源代码
Array.prototype.forEach = function (fn) {
for (let i = 0; i < this.length; i++){
if (i in this) {
fn.call(undefined,this[i],i,this)
}
}
}
-
forEach
和for
的主要区别:
-
forEach
没有break
,除了抛出异常以外,没有办法中止或跳出 forEach() 循环。 -
forEach
用到了函数,所以每次迭代都会有一个新的函数作用域,而for
循环只有一个作用域
//著名面试题for(var i = 0; i< 6; i++)
let item = [1, 2, 3, 4, 5, 6]
item.forEach((item, index) => {
item.onclick = function () {
cosnoel.log(index)
}
})
map
- MDN定义:
map()
方法创建一个新数组,其结果是该数组中的每个元素都调用一次提供的函数后的返回值。原数组不变,返回一个新数组
var array = [1, 2, 3, 4];
var newArray = array.map(element => element * 2);
console.log(array); //[1, 2, 3, 4]
console.log(newArray); //[2,4,6,8]
- 由于
map()
和firEach()
功能差不多,区别只有返回值而已,所以只用map()
即可。 - 推测类似源代码
Array.prototype.map = function (fn) {
let result = []
for (let i = 0; i < this.length; i++){
if (i in this) {
result[i] = fn.call(undefined,this[i],i,this)
}
}
return result
}
filter(过滤)
- MDN定义:
filter()
方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。原数组不变,返回一个新数组,如果没有元素通过测试则返回空数组。等价于有条件放入的map()
。
var a = [1, 2, 3, 4, 5, 6, 7, 8];
a.filter((element) => {
return element % 2 === 0;
});
//[2,4,6,8]
- 六个假值:
false | 0 | ' ' | NaN | null | undefined
-
find()
与filter()
的区别
//Array.prototype.find 找到第一个符合条件的对象就停止查找
//Array.prototype.filter过滤出所有符合条件的对象
var a = [
{ name: "a1", age: 80 },
{ name: "a2", age: 18 },
{ name: "a3", age: 18 }
];
console.log(a.find(item => item.age === 18)); //{name:'a2',age:18}
console.log(a.filter(item => item.age === 18)); //{{name:'a2',age:18},{name: 'a3',age:18}}
- 推测类似源代码
Array.prototype.filter = function (fn) {
let result = []
let temp
for (let i = 0; i < this.length; i++){
if (i in this) {
if (temp = fn.call(undefined, this[i], i, this)) {
result.push(temp)
}
}
}
return result
}
//fn.call返回真值就push到返回值,不是真值就不push。
reduce
- MDN定义:
reduce()
方法对数组中的每个元素执行一个由您提供的reducer函数
(升序执行),将其结果汇总为单个返回值。原数组不变。
var a = [1, 2, 3, 4];
a.reduce((result,item,index,array) => {return result + item}) //10
- 您的 reducer 函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。即把上次的结果加上当前的数组元素作为当前的结果。
- 注意:如果没有提供
initialValue
,reduce
会从索引1的地方开始执行callback 方法
,跳过第一个索引。如果提供initialValue
,从索引0开始。 - 将二维数组转换为一维数组
var a = [
[1, 2],
[4, 5],
[6, 9],
];
let b = a.reduce((acc, cur) => {
return acc.concat(cur); // concat() 方法用于合并两个或多个数组。
});
console.log(b) //[1, 2, 4, 5, 6, 9]
- 计算数组中每个元素出现的次数
let name = ["Alice", "Bob", "Tiff", "Alice", "lili", "zhang", "lili", "Alice"];
let b = name.reduce((nameCount, element) => {
if (element in nameCount) {
nameCount[element]++;
} else {
nameCount[element] = 1;
}
return nameCount;
}, {});
console.log(b) // {Alice: 3, Bob: 1, Tiff: 1, lili: 2, zhang: 1}
- 数组去重 --- ES5
var a = [1, 2, 5, 4, 5, 3, 2, 1, 3];
function uniq(array) {
var result = [];
var hash = {};
for (var i = 0; i < array.length; i++) {
hash[array[i]] = true; //把数组的值作为对象的key,存储起来,并且赋值true,相同的数值不进行多次处理
}
console.log(hash);
for (let key in hash) {
result.push(key); //把hash对象的key push到数组里
}
return result;
}
console.log(uniq(a)); //['1','2','3','4','5']
/*
缺点:
1: 返回的新数组里面的数字不是真实的数字,是字符串数字,因为在ES6之前,对象的属性名只能是字符串
2. 无法区别原数组中的数字和字符串数字,比如'4'和4,会被认为是一个
3. 无法统计对象,比如[1,2,3,{name:object}] //返回的新数组是["1", "2", "3", "[object Object]"]
*/
- 数组去重---ES6
//set对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用
var a = [1, 2, 5, 4, 5, "4", 3, 2, 1, 3, { name: "object" }];
function uniq(array) {
return Array.from(new Set(array));
//等价于[...new Set(array)]
}
//new Set(array)得到的是对象,所以Array.form将对象变为数组
console.log(uniq(a)); //[1, 2, 5, 4, "4", 3, {…}]
-
map()
可以用reduce()
表示
array2 = array.map((v) => v + 1)
//reduce写法
array2 = array.reduce((result, v) => {
result.push(v + 1)
return result
},[])
-
filter()
可以用reduce()
表示
array2 = array.filter((v) => v % 2 === 0)
//reduce写法
array2 = array.reduce((result, v) => {
if (v % 2 === 0) {
result.push(v)
}
return result
},[])
- 推测类似源代码
Array.prototype.reduce = function (fn, init) {
let result = init
for (let i = 0; i < this.length; i++){
if (i in this) {
result = fn.call(undefined,result,this[i],i,this)
}
}
return result
}
创建长度为n并且每一项都是指定项的数组
- MDN定义:
Array.from()
方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。 - MDN定义:
fill()
方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。 - ES5
function x(n, fill) {
return new Array(n + 1).join(fill).split("");
}
console.log(x(6, 6)); //["6", "6", "6", "6", "6", "6"]
- ES6
function x(n, fill) {
var array = Array.from({ length: n });
return array.map(v => fill);
//上面两句话等价于 rreturn Array.form({length:n}).fill(fill)
}
console.log(x(6, 6)); //[6, 6, 6, 6, 6, 6]
创建一个长度为n并且有下标的数组
//ES5 得到一个长度为5的数组,但是没有任何下标
a = new Array(5);
console.log(a); //[empty × 5]
// ES6创建长度为5,但是有下标的数组
a = Array.from({ length: 5 });
console.log(a); //[undefined, undefined, undefined, undefined, undefined]
//ES5近似实现方法
a = Array.apply(null, { length: 5 });
console.log(a); //[undefined, undefined, undefined, undefined, undefined]
Underscore.js
Underscore.js
是关于操作数组并且使用做广泛的一个库,Underscore.js
是一个集合操作的库,当时js 没有set,所以集合指的是数组和对象。loadsh.js
也是操作数组的库,是在Underscore.js
上的扩充。