4

JavaScript基础 - - 数组

数组是一个有序的数据集合,使用数组名称和索引进行访问。

let arr = [1,2,3];
arr[0] = 1;

在JavaScript中数组没有明确数据类型。

let arr = [1, 'hi', undefined, fun()];

1.创建数组

创建数组方法有3种:

let arr = new Array(ele1, ele2, ele3, ..., eleN);
let arr = Array(ele1, ele2, ele3, ..., eleN);
let arr = [ele1, ele2, ele3, ..., eleN];

上面是已知数组元素,另外一种还有创建一个长度不为0,且有没有任何元素的数组

let len = 5;

let arr = new Array(len); // 方法1
let arr = Array(len);     // 方法2
let arr = [];             // 方法3
arr.length = len;

若传入的数组长度不是整数,则报错:

let arr = new Array(3.5); 
let arr = Array(3.5); 
let arr = [];
arr.length = 3.5;
//Uncaught RangeError: Invalid array length

其中要注意这两种创建方法是不同的:

let arr1 = new Array(4);   // [empty × 4]
let arr2 = [4];            // [4]
for(let k in arr1){
    console.log(k);
}  // undefined
for(let k in arr2){
    console.log(k);
}  // 0

2.使用数组

2.1 简单使用

获取数组指定位置的值:

let a = [1,2,5];
a[0];  // 1
a[2];  // 5
a[3];  // undefined

获取数组长度:

let a = [1,2,5];
a.length;    // 3
a["length"]; // 3

设置数组指定位置的值:

let a = [1,2,5];
a[0] = 9;
a[2] = 99;
a[3] = 999;

2.2 理解数组length

  • 数组的索引值是从0开始,即上面数组索引0的是1,索引1的值是2,依次下去。
  • 数组length永远返回的是数组最后一个元素的索引加1。
  • 可通过arr.length = 0来清空数组。
  • 可通过arr.length = len来设置数组长度。

2.3 遍历数组

遍历数组就是以某种方法处理数组的每个元素,简单如下:

  • 使用for循环:
let arr = ["pingan", "leo", "robin"];
for (let i = 0; i<arr.length; i++){
    // 处理元素的操作
    console.log(`第${i}个元素是:${arr[i]};`)
}
// 第0个元素是:pingan;
// 第1个元素是:leo;
// 第2个元素是:robin;
  • 使用for...in
let arr = ["pingan", "leo", "robin"];
for(let i in arr){
    console.log(`第${i}个元素是:${arr[i]};`)
}
// 第0个元素是:pingan;
// 第1个元素是:leo;
// 第2个元素是:robin;
  • 使用forEach

arr.forEach(callback) 接收一个回调方法。

callback(val, index, array) : 接收三个参数:

  • val : 当前处理的元素;
  • index : 当前处理的元素的索引;
  • array : 正在处理的数组;

可参考MDN Array.prototype.forEach 的详细介绍。

let arr = ["pingan", "leo", "robin"];
arr.forEach(function(val, i, array){
    console.log(`第${i}个元素是:${val};`)
})

3. 数组方法(访问和修改)

方法名称方法介绍
concat()连接两个或更多的数组,并返回结果。
join()把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
pop()删除并返回数组的最后一个元素
push()向数组的末尾添加一个或更多元素,并返回新的长度。
reverse()颠倒数组中元素的顺序。
shift()删除并返回数组的第一个元素
slice()从某个已有的数组返回选定的元素
sort()对数组的元素进行排序
splice()删除元素,并向数组添加新元素。
toSource()返回该对象的源代码。
toString()把数组转换为字符串,并返回结果。
toLocaleString()把数组转换为本地数组,并返回结果。
unshift()向数组的开头添加一个或更多元素,并返回新的长度。
valueOf()返回数组对象的原始值
indexOf()在数组中搜索指定元素并返回第一个匹配的索引
lastIndexOf()在数组中搜索指定元素并返回最后一个匹配的索引

可参考W3school JavaScript Array 对象 的详细介绍。

3.1 concat()

连接两个或更多的数组,并返回一个新数组。

  • 语法:

arr.concat(a1, a2, ..., an);

  • 参数:

arr:目标数组;

a1,a2,...,an:需要合并的元素;

let a1 = [1,2,3];
let a2 = [9,99,999];
let a = a1.concat(a2);
// [1, 2, 3, 9, 99, 999]

3.2 join()

使用指定分隔符,连接两个或多个数组的元素,返回一个字符串。

  • 语法:

arr.join(sep);

  • 参数:

arr:目标数组;

sep:连接的分隔符,默认值为“,”;

let arr = ["pingan", "leo", "robin"];
arr.join();    // "pingan,leo,robin"
arr.join("");  // "pinganleorobin"
arr.join(","); // "pingan,leo,robin"

3.3 pop()和push()

  • pop(): 删除并返回数组最后一个元素改变原数组
  • push(item): 向数组末尾添加一个或多个元素,改变原数组,返回新的数组长度。

方便记忆和理解:两个都是从数组末尾操作,pop()是删除最后一个元素,push()是向最后一位添加新的元素。

let arr = ["pingan", "leo"];
let a1 = arr.pop();              // "leo"
let a2 = arr.push("robin","hi"); // 3
arr;   // ["pingan", "robin", "hi"]

3.4 shift()和unshift()

  • shift(): 删除并返回数组第一个元素改变原数组
  • unshift(item): 向数组头部添加一个或多个元素,改变原数组,返回新的数组长度。

方便记忆和理解:两个都是从数组头部操作,shift()是删除第一个元素,unshift()是向第一位添加新的元素。

let arr = ["pingan", "leo"];
let a1 = arr.shift();               // "pingan"
let a2 = arr.unshift("robin","hi"); // 3
arr;   // ["robin", "hi", "leo"]

3.5 reverse()

颠倒数组中元素的顺序,改变原数组

let arr = [1, 2, 3, 4];
arr.reverse();  // [4, 3, 2, 1]

3.6 slice()

用于提取数组中一个片段,作为新数组返回。

slice(start[,end]): 接收2个参数:

  • start:  必需,指定起始索引,若负数则从数组最后开始算起,-1为倒数第一位,-2为倒数第二位,以此类推。
  • end: 可选,指定结束索引,若没传则表示到数组结束。

注意

end若有指定的话,是不包含end索引上的值。

let arr = [1, 2, 3, 5, 6];
let a1 = arr.slice(2);    // [3, 5, 6]
let a2 = arr.slice(2,3);  // [3]

3.7 splice()

从数组中删除指定索引开始的项目,然后返回被删除的项目。

  • 语法:

arr.splice(index, num, a1, a2,...,an);

  • 参数:

index: 必需,起始位置的索引,若负数则从数组最后开始算起;

num:必需,删除的数量,若为0则不删除;

a1,a2,...an:可选,为数组添加的元素;

let arr = [1, 2, 3, 4];
let a = arr.splice(1, 2, "hi", "leo");
// a =>  [2, 3]
// arr =>  [1, "hi", "leo", 4]

3.8 sort()

对数组的元素进行排序,改变原数组

可接受一个回调方法作为比较函数,来决定排序方式。

比较函数应该具有两个参数 ab,返回值如下:

a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。

a 等于 b,则返回 0。

a 大于 b,则返回一个大于 0 的值。

let a1 = [1,3,6,9,10];
a1.sort(); // [1, 10, 3, 6, 9]
a1.sort(function(a,b){
    return a > b ? 1 : a < b ? -1 : 0;
})         // [1, 3, 6, 9, 10]

3.9 indexOf()和lastIndexOf()

两者都是在数组搜索指定元素,只是indexOf()返回的是搜索到的第一个元素的索引,而lastIndexOf()返回的是搜索到的最后一个元素的索引。

语法:

indexOf(ele[,start])lastIndexOf(ele[,start]);

参数:

  • ele:  需要搜索的元素。
  • start:  开始搜索的索引。
let arr = ["hh1", "hh2", "hh2", "hh2", "hh3", "hh4"];
let a1 = arr.indexOf("hh2");      // 1
let a2 = arr.lastIndexOf("hh2");  // 3
let a3 = arr.indexOf("hh2",2);    // 2

4. 数组方法(迭代)

方法名称方法介绍
forEach()为数组中的每个元素执行一次回调函数。
every()如果数组中的每个元素都满足测试函数,则返回 true,否则返回 false。
some()如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。
filter()将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回。
map()返回一个由回调函数的返回值组成的新数组。
reduce()从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。
reduceRight()从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。

以下是ES6规范新增的数组方法:

方法名称方法介绍
keys()返回一个数组迭代器对象,该迭代器会包含所有数组元素的键。
values()返回一个数组迭代器对象,该迭代器会包含所有数组元素的值。
entries()返回一个数组迭代器对象,该迭代器会包含所有数组元素的键值对。
find()找到第一个满足测试函数的元素并返回那个元素的值,如果找不到,则返回 undefined。
findIndex()找到第一个满足测试函数的元素并返回那个元素的索引,如果找不到,则返回 -1。

可参考MDN Array 的详细介绍。

4.1 forEach()

对数组的每个元素执行一次提供的函数。

语法:

arr.forEach(callback)

参数:

callback(val, index, arr) : 需要执行的函数,接收三个参数:

  • val : 正在处理的当前元素;
  • index : 可选,正在处理的当前元素的索引;
  • arr : 可选,正在操作的数组;
let a = [1,3,5,7];
a.forEach(function(val, index, arr){
    arr[index] = val * 2
})
a ; // [2, 6, 10, 14]

4.2 every()

测试数组的所有元素是否都通过了指定函数的测试。

语法:

arr.every(callback)

参数:

callback(val, index, arr) : 需要执行的函数,接收三个参数:

  • val : 正在处理的当前元素;
  • index : 可选,正在处理的当前元素的索引;
  • arr : 可选,正在操作的数组;

返回值:

若都通过返回true,否则返回false

let a = [1, "", "aa", 13, 6];
let res = a.every(function(val, index, arr){
    return typeof val == "number";
})
res;// false

let b = [1, 2, 3];
let r = b.every(function(val, index, arr){
    return typeof val == "number";
})
r;  // true

4.3 some()

测试数组中的某些元素是否通过由提供的函数实现的测试。

语法:

arr.some(callback)

参数:

callback(val, index, arr) : 需要执行的函数,接收三个参数:

  • val : 正在处理的当前元素;
  • index : 可选,正在处理的当前元素的索引;
  • arr : 可选,正在操作的数组;

返回值:

若有一个通过返回true,否则返回false

let a = [1, "", "aa", 13, 6];
let res = a.some(function(val, index, arr){
    return typeof val == "number";
})
res;// true

let b = [1, 2, 3];
let r = b.some(function(val, index, arr){
    return typeof val == "number";
})
r;  // true

4.4 filter()

将所有在过滤函数中返回 true 的数组元素放进一个新数组中并返回。

语法:

arr.filter(callback)

参数:

callback(val, index, arr) : 需要执行的函数,接收三个参数:

  • val : 正在处理的当前元素;
  • index : 可选,正在处理的当前元素的索引;
  • arr : 可选,正在操作的数组;

返回值:

一个返回通过测试的元素的数组,若都没有则返回空数组。

let a = [1, "", "aa", 13, 6];
let res = a.filter(function(val, index, arr){
    return typeof val == "number";
})
res;//[1, 13, 6]

4.5 map()

传入一个操作函数,对每个元素执行此方法,并返回一个执行后的数组。

语法:

arr.map(callback)

参数:

callback(val, index, arr) : 需要执行的函数,接收三个参数:

  • val : 正在处理的当前元素;
  • index : 可选,正在处理的当前元素的索引;
  • arr : 可选,正在操作的数组;

返回值:

一个新数组,每个元素都是回调函数的结果。

let a = [1, 3, 5];
let b = a.map(function(val, index, arr){
    return val + 2;
})
b; //[3, 5, 7]

5. 数组的拓展(ES6)

5.1 拓展运算符

拓展运算符使用(...),类似rest参数的逆运算,将数组转为用(,)分隔的参数序列。

console.log(...[1, 2, 3]);   // 1 2 3 
console.log(1, ...[2,3], 4); // 1 2 3 4

拓展运算符主要使用在函数调用。

function f (a, b){
    console.log(a, b);
}
f(...[1, 2]); // 1 2

function g (a, b, c, d, e){
    console.log(a, b, c, d, e);
}
g(0, ...[1, 2], 3, ...[4]); // 0 1 2 3 4

若拓展运算符后面是个空数组,则不产生效果

[...[], 1]; // [1]

替代apply方法

// ES6之前
function f(a, b, c){...};
var a = [1, 2, 3];
f.apply(null, a);

// ES6之后
function f(a, b, c){...};
let a = [1, 2, 3];
f(...a);

// ES6之前
Math.max.apply(null, [3,2,6]);

// ES6之后
Math.max(...[3,2,6]);

拓展运算符的运用

  • (1)复制数组

通常我们直接复制数组时,只是浅拷贝,如果要实现深拷贝,可以使用拓展运算符。

// 通常情况 浅拷贝
let a1 = [1, 2];
let a2 = a1; 
a2[0] = 3;
console.log(a1,a2); // [3,2] [3,2]

// 拓展运算符 深拷贝
let a1 = [1, 2];
let a2 = [...a1];
// let [...a2] = a1; // 作用相同
a2[0] = 3;
console.log(a1,a2); // [1,2] [3,2]
  • (2)合并数组

注意,这里合并数组,只是浅拷贝。

let a1 = [1,2];
let a2 = [3];
let a3 = [4,5];

// ES5 
let a4 = a1.concat(a2, a3);

// ES6
let a5 = [...a1, ...a2, ...a3];

a4[0] === a1[0]; // true
a5[0] === a1[0]; // true
  • (3)与解构赋值结合

与解构赋值结合生成数组,但是使用拓展运算符需要放到参数最后一个,否则报错。

let [a, ...b] = [1, 2, 3, 4]; 
// a => 1  b => [2,3,4]

let [a, ...b] = [];
// a => undefined b => []

let [a, ...b] = ["abc"];
// a => "abc"  b => []

5.2 Array.from()

类数组对象可遍历的对象,转换成真正的数组。

// 类数组对象
let a = {
    '0':'a',
    '1':'b',
    length:2
}
let arr = Array.from(a);

// 可遍历的对象
let a = Array.from([1,2,3]);
let b = Array.from({length: 3});
let c = Array.from([1,2,3]).map(x => x * x);
let d = Array.from([1,2,3].map(x => x * x));

5.3 Array.of()

将一组数值,转换成数组,弥补Array方法参数不同导致的差异。

Array.of(1,2,3);    // [1,2,3]
Array.of(1).length; // 1

Array();       // []
Array(2);      // [,] 1个参数时,为指定数组长度
Array(1,2,3);  // [1,2,3] 多于2个参数,组成新数组

5.4 find()和findIndex()

find()方法用于找出第一个符合条件的数组成员,参数为一个回调函数,所有成员依次执行该回调函数,返回第一个返回值为true的成员,如果没有一个符合则返回undefined

[1,2,3,4,5].find( a => a < 3 ); // 1

回调函数接收三个参数,当前值、当前位置和原数组。

[1,2,3,4,5].find((value, index, arr) => {
    // ...
});

findIndex()方法与find()类似,返回第一个符合条件的数组成员的位置,如果都不符合则返回-1

[1,2,3,4].findIndex((v,i,a)=>{
    return v>2;
}); // 2

5.5 fill()

用于用指定值填充一个数组,通常用来初始化空数组,并抹去数组中已有的元素。

new Array(3).fill('a');   // ['a','a','a']
[1,2,3].fill('a');        // ['a','a','a']

并且fill()的第二个和第三个参数指定填充的起始位置结束位置

[1,2,3].fill('a',1,2);//  [1, "a", 3]

5.6 entries(),keys(),values()

主要用于遍历数组,entries()对键值对遍历,keys()对键名遍历,values()对键值遍历。

for (let i of ['a', 'b'].keys()){
    console.log(i)
}
// 0
// 1

for (let e of ['a', 'b'].values()){
    console.log(e)
}
// 'a'
// 'b'

for (let e of ['a', 'b'].entries()){
    console.log(e)
}
// 0 'a'
// 1 'b'

5.7 includes()

用于表示数组是否包含给定的值,与字符串的includes方法类似。

[1,2,3].includes(2);     // true
[1,2,3].includes(4);     // false
[1,2,NaN].includes(NaN); // true

第二个参数为起始位置,默认为0,如果负数,则表示倒数的位置,如果大于数组长度,则重置为0开始。

[1,2,3].includes(3,3);    // false
[1,2,3].includes(3,4);    // false
[1,2,3].includes(3,-1);   // true
[1,2,3].includes(3,-4);   // true

5.8 flat(),flatMap()

flat()用于将数组一维化,返回一个新数组,不影响原数组。

默认一次只一维化一层数组,若需多层,则传入一个整数参数指定层数。

若要一维化所有层的数组,则传入Infinity作为参数。

[1, 2, [2,3]].flat();        // [1,2,2,3]
[1,2,[3,[4,[5,6]]]].flat(3); // [1,2,3,4,5,6]
[1,2,[3,[4,[5,6]]]].flat('Infinity'); // [1,2,3,4,5,6]

flatMap()是将原数组每个对象先执行一个函数,在对返回值组成的数组执行flat()方法,返回一个新数组,不改变原数组。

flatMap()只能展开一层。

[2, 3, 4].flatMap((x) => [x, x * 2]); 
// [2, 4, 3, 6, 4, 8]

6. 数组的拓展(ES7)

6.1 Array.prototype.includes()方法

includes()用于查找一个值是否在数组中,如果在返回true,否则返回false

['a', 'b', 'c'].includes('a');     // true
['a', 'b', 'c'].includes('d');     // false

includes()方法接收两个参数,搜索的内容开始搜索的索引,默认值为0,若搜索值在数组中则返回true否则返回false

['a', 'b', 'c', 'd'].includes('b');      // true
['a', 'b', 'c', 'd'].includes('b', 1);   // true
['a', 'b', 'c', 'd'].includes('b', 2);   // false

indexOf方法对比,下面方法效果相同:

['a', 'b', 'c', 'd'].indexOf('b') > -1;  // true
['a', 'b', 'c', 'd'].includes('b');      // true

includes()与indexOf对比:

  • includes相比indexOf更具语义化,includes返回的是是否存在的具体结果,值为布尔值,而indexOf返回的是搜索值的下标。
  • includes相比indexOf更准确,includes认为两个NaN相等,而indexOf不会。
let a = [1, NaN, 3];
a.indexOf(NaN);     // -1
a.includes(NaN);    // true

另外在判断+0-0时,includesindexOf的返回相同。

[1, +0, 3, 4].includes(-0);   // true
[1, +0, 3, 4].indexOf(-0);    // 1

参考资料

1.MDN 索引集合类
2.MDN 数组对象

JS中的数组是弱类型的,数组中可以含有不同类型的元素。数组元素甚至可以是对象或其它数组。
JS引擎一般会优化数组,按索引访问数组常常比访问一般对象属性明显迅速。
数组长度范围 from 0 to 4,294,967,295(2^23 - 1)

JavaScript 中的数据通常由一个数组来表示, 所以当可视化或分析数据时往往也会操作数组. 常见的数组操作包括切片, 过滤, 遍历等等. JavaScript 本身支持的数组操作可以参考 这里.

主要分为三大类:
JavaScript 中 修改数组自身 的方法:

  • array.pop - 移除最后一个元素.
  • array.push - 追加一个或多个元素.
  • array.reverse - 数组翻转.
  • array.shift - 移除第一个元素.
  • array.sort - 排序.
  • array.splice - 添加或者移除.
  • array.unshift - 在数组前添加一个或多个元素.

JavaScript 中数组的 存取 方法 :

  • array.concat - 将数组与数组或值合并.

图片描述

再看看解构方法

const arr1 = [1,2,3];
const arr2 = [4,5,6];

const result = [...arr1, ...arr2];
  • array.join - 只用指定的字符串将数组转为一个字符串.
  • array.slice - 提取切片.
  • array.indexOf - 找出指定元素的索引.(搜索)
  • array.lastIndexOf - 找出指定元素的最后一个索引.

JavaScript 中数组的 迭代方法 :

  • array.filter - 过滤.
  • array.forEach - 对每个元素执行某个方法.
  • array.every - 是否每个元素都符合给定的条件.
  • array.map - 根据指定的操作对每个元素执行后返回一个新的数组.
  • array.some - 是否存在符合某个条件的元素.
  • array.reduce - 从左到右执行 reduce 操作并返回一个值.
  • array.reduceRight - 从右到左执行 reduce 操作并返回一个值.

基础

数组在数学中也可以称为“数列”,也就是以数字或其他类型内容为元素的有序集合。

// 整型数字数组
const intArray = [ 1, 2, 3, 4, 5 ]
// 浮点型数字数组
const floatArray = [ 1.1, 1.2, 1.3, 1.4, 1.5 ]
// 字符串数组
const strArray = [ 'a', 'b', 'c', 'd', 'e' ]...

在数据科学领域中,数组可以说是承载了绝大部分数据的表达任务,无论是规整的数据表,还是随时间排序的时间序列,或是复杂多变的非结构化数据,都可以使用数组或类数组的形式表达。

数组创建

图片描述

数组读写

图片描述

数组 VS. 一般对象

相同点

  • 数组是对象,对象不一定是数组
  • 都可以继承
  • 都可以当做对象添加删除属性

不同点

  • 数组自动更新length
  • 数组操作通常被优化
  • 数组对象继承Array.prototype上的大量数组操作方法

稀疏数组

稀疏数组并不含有从0开始的连续索引。一般length属性值比实际元素个数大。
图片描述

图片描述

for in 可以枚举可枚举属性名,对象,数组都是可以使用的,可以把数组理解为一种特殊的对象,常用for in枚举稀疏数组

数组的length属性

我们前面讲到数组是一个有序集合,那么就意味着它包含了若干个元素。当然了,数组可空。因为它是一个包含了若干元素的集合,所以它就肯定天然地包含了一个属性,那便是元素的数量。

图片描述

const array = [ 1, 2, 3, 4, 5 ]
console.log(array.length) //=> 5

增删改查

因为在计算机中的可用内存是有限的,所以大部分程序在创建数据(比如数组)的时候,都需要先设定好该数据的所占长度。但在 JavaScript 中这并不需要,因为实际在 JavaScript 中数组就是一个特殊的对象。

所以在 JavaScript 中,对数组内容的修改会比较方便。“增查改删”是数据库应用领域中最常见的操作,这在数组中也是一样的。

添加到末端append

  • array.push

图片描述

添加首端prepend

图片描述

添加到中间insert

图片描述

array.splice(start, deleteCount, element)

  • 第二个参数deleteCount用来删除数组中某个位置开始的若干个元素
  • 如果设置为0,该方法第三参数以及后面的参数会被插入到start位置(array[start]开始)

删除数组中某特定元素

    let keys = ['纯新客', '品类转化新客', '老客']
    keys.splice(keys.indexOf('纯新客'), 1)

图片描述

vue源码中就用的此方法

/**
 * Remove an item from an array
 */
function remove (arr, item) {
  if (arr.length) {
    var index = arr.indexOf(item);
    if (index > -1) {
      return arr.splice(index, 1)
    }
  }
}

查找内容

数组是个有序集合,我们在对数组中的元素进行查找的时候也是一个有序进行的过程,而最常用的查找方法便是filter过滤器.

过滤器的逻辑是:定义一个过滤函数,该函数会有序地被传入数组中当前下标的元素,而它则需返回该函数是否符合其过滤要求,即结果为truefalse
在数组中找出偶数项:

图片描述

判断字符串是否是数组中元素

常用于权限验证

图片描述

字符串转数组

图片描述

图片描述

数组转字符串

图片描述
图片描述

判断是否是数组

Array.isArray([]);//true
[] instanceof Array; //true
({}).toString.apply([])==='[object Array]';//true
[].constructor ===Array;//true


js实现对象-数组-字符串之间的相互转化
对象-数组-字符串:  

  例如:
  var data = {
           user:”userName”,
       pass:”12121”
  };//这是一个对象
  
  如果要给这个data 对象追加一个属性就比如:
 
  new Date( ).getTime( );//获取当前时间到那个时间的时间间隔单位是毫秒;
 
  data.time = new Date( ).getTime( );
 
  此时data 里面就多了一个属性: time : “ 获取到的那个毫秒数"      
  即: var data = {
      user:”userName”,
      pass:”12121”
      time:"获取的时间数值"
     };
 
 1: 对象转化为数组:
 
  var arr = [ ];
   for ( var i in data ){
            var str = i + “=“ + data[ i ]// i 就代表 data 里面的 user pass 等等 而data[ i ] 就代表 userName    12121 就是 i 所对应的值;
            arr.push( str );
  }
  这样就会得到 arr  =  [ user = userName, pass = 12121 ];
  
 2:数组转化为字符串:
  
  两种方法:
    1:arr.join( “&”)//意思是用&f符代替“ , ”然后把数组变成字符串连接;          这时候 arr 里面的内容就是 user = tangcaiye&pass = 12121
    2: 比如:
      var arr = [1,2];
      var str = JSON.stringify(arr);//这样也能转化为字符串但现在还是数组的形式不过类型已经是字符串了;
      var arr2 = JSON.parse(str);//这样就是把字符串解析 其实就是把外面的中括号去掉;
 
    前后台交互的:
    后台接收的时候只能接收字符串类型的;
    如果前台要传递一个数组就必须先把数组进行stringify( )的操作再进行传递;
    而后台返回给前台的也是字符串简称json串;这时需要解析一下就需要 JSON.parse( );操作完了再用;
 
 3:字符串转化为数组:
  
  例如:
  有个这样的 : url = “login.php?user=“+user.value+”&pass=“+pass.value;
 
  那我想要得到login.php就是这样写:var urlArr = url.split(“?”);
 
  上面那个意思就是以?为分割点把这个字符串劈开变成一个数组的两部分;
 
  那么 aa = urlArr[0];此时 aa 就等于 login.php;
  bb = urlArr[1];此时bb 就等于 后面那一坨

    

怎么实现range函数

js怎么实现类似python的range函数

Array.apply(null, {length: N}).map(Number.call, Number)为range的hack;
图片描述

图片描述

图片描述
图片描述

对象转数组

Array.from()ES6为Array增加了from函数用来将其他对象转换成数组
图片描述

当然,其他对象也是有要求,也不是所有的,可以将两种对象转换成数组。

1.部署了Iterator接口的对象,比如:Set,Map,Array。

2.类数组对象,什么叫类数组对象,就是一个对象必须有length属性,没有length,转出来的就是空数组。

比如:

arguments对象不是数组,而是一个类似数组的对象。所以为了使用数组的方法,必须使用Array.prototype.slice.call先将其转为数组。rest 参数就不存在这个问题,它就是一个真正的数组,数组特有的方法都可以使用。

// arguments变量的写法
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();

这里用到的 rest参数

图片描述

在数组中搜索

图片描述

数组转对象

图片描述

注意这里加了键值 0

用concat()和apply()将一个两维数组扁平化

使用Array对象的 concat() 方法,将多维数组合并为一个单维数组:

图片描述

删除或替换数组元素

使用Array的indexOf()和splice()方法,找到并删除/替换数组元素 

图片描述

图片描述

提取一个数组的一部分

使用Array对象的slice()方法,来提取已有数组的一部分的一个浅拷贝(shallow copy)

图片描述
图片描述
图片描述
注意slice()方法复制一个已有的数组的一部分,返回一个新数组。
它执行的是浅拷贝,这意味着:

  • 如果数组元素是对象,两个数组都指向相同的对象,对新数组中的对象修改,会在旧的数组的相同对象中反应出来。

图片描述

  • 如果数组元素是基本数据类型,例如,字符串或数字,它们将按照值(by value)来复制(值是按照引用来复制的),也就是说,对新数组的修改,不会在旧数组中反映出来(如最上面的例子)

图片描述

对每个数组元素应用一个函数

图片描述

注意: 不要从传递给forEach的函数返回一个值,因为该值会被丢弃
但是用map就需要
因为:map()的结果是一个新的数组,而不是像forEach()一样修改最初的数组

图片描述

使用forEach() and call() 遍历querySelectAll()的结果

可以将forEach()强制地和一个NodeList(querySelectorAll()返回的集合)一起使用
//使用querySelector找到第二列中的所有单元格
var cells = document.querySelectorAll("td+td");
[].forEach.call(cells, function(cell) {
  sum += parseFloat(cell.firstChild.data);
});

数组去重

sort()方法排序后比较

var arr = [1, 2, 3, 1, 2, 3, 4, 5, 5];
var resultArr = [];
//使用数组的sort()方法对arr进行排序,也可以使用冒泡排序
arr.sort(function (a, b) {
    return a - b;
});
//排序后,arr变成了[1, 1, 2, 2, 3, 3, 4, 5, 5]

//使用for循环,从上面的数组可以看出,如果数组元素arr[i]和arr[i+1]不相等,则表示arr[i]之后不再有与arr[i]相等的重复元素
for (i = 0; i < arr.length; i++) {
    if (arr[i] != arr[i + 1]) {
        //将arr[i]赋值给resultArr数组.
        resultArr[resultArr.length] = arr[i];
    }
}
console.log(resultArr); //1,2,3,4,5

set方法

[...new Set([2,"12",2,12,1,2,1,6,12,13,6])]
    
    // [2, "12", 12, 1, 6, 13]

图片描述

在这我们可以看见,重复的项目已经被去掉了,包括NaN。正常情况下,NaN === NaN 返回的是false,但是在set里,一样能够帮你去重

但是这里大家可以看到,set返回的是一个对象,但是我们想要的是数组啊。

这回,就该轮到Array.from出场了,它的作用,就是可以把类数组对象、可迭代对象转化为数组。
图片描述
图片描述

filter方法

clipboard.png

缓存方法

clipboard.png

lodash实现

移除一个数组中的重复元素, 这些元素可能是多种不同数据类型
Lodash如何从数组中删除重复项?

数组元素比大小

找出数组中的最小值

图片描述

找出数组中的最大值

图片描述

快速的让一个数组乱序

var arr = [1,2,3,4,5,6,7,8,9,10];
    arr.sort(function(){
        return Math.random() - 0.5;
    })
    console.log(arr);

图片描述

首先: 当return 的值

    小于 0 ,那么 a 会被排列到 b 之前;
    等于 0 , a 和 b 的相对位置不变;
    大于 0 , b 会被排列到 a 之前;

这里你会 发现起始 的时候数组是正序排列,每当进行一次排列的时候, 都会先随机一个随机数 
(注意这里的每一次排列 指 每一个红框指一次排列, 共9次排列 , 一次排列中可能存在多次比较);

当一次排列的 随机数大于0.5 时 将会进行第二次比较, 当第二次随机数 仍然大于0.5 时 ,
    将会再 进行一次比较, 直到 随机数大于0.5 或者排列到第一位;

当一次排列的 随机数 小于0.5时 当前比较的两项 索引将不会改变 ,继续下一次 的排列;

数组求最大值

图片描述

复制数组

图片描述

数组合并

图片描述

图片描述

注意和下面的区别
图片描述

图片描述

迭代输出

图片描述

数组内元素求和

图片描述
更多查看Array.prototype.reduce()
这是reduce实现过程:

Array.prototype.reduce=function(callback){
    var total=0;
    this.forEach(function(e){ total=callback(total,parseInt(e));});
   return total;

 };

检测数组中是否存在满足某些条件的元素:

let arr = [2, 5, 8, 1, 4, 17, 89]

// filter 实现
let result = arr.filter(item => {
    return item > 9
}).length > 0


// find 实现
let result = arr.find(item => {
    return item > 9
})  !== undefined


// some 实现
let result =  arr.some(item => {
    return item > 9
})

d3-array

下面是d3-array中涉及的一些数组操作
图片描述

统计类方法 Statistics

对指定的 array 进行自然排序返回最小值. 如果数组为空则返回 undefined. 可选的参数 accessor 可以用来自定义如何访问数组中的元素. accessor 将会被传递给 map 以在数组的每个元素上进行调用, 返回值将会被作为对比依据.

与内置的 Math.min 不同, 这个方法可以忽略 undefined, null 和 NaN 等特殊值. 在可视化中用来忽略缺失数据是很有用的. 需要注意的是, 对比是以自然排序进行的, 而非数值对比. 比如对字符串 ['20', '3'] 进行 min 操作返回 20, 而对数值 [20, 3] 进行 min 操作则返回 3.

笛卡尔乘积

d3.cross

图片描述

方差

d3.variance(array[, accessor]): 准确的说它返回的是总体方差无偏估计量
图片描述

将数组中相邻的两个元素两两结合

图片描述

数组元素最大值

图片描述

数组元素占最大值比例(数据归一化)

图片描述

lodash

常见数组操作问题

let a = [ { name:"1", status:"1" }, { name:"2", status:"1" }, { name:"3", status:"2" }, { name:"4", status:"2" }, { name:"5", status:"3" }, { name:"6", status:"bbb" } ]
     
{ '1':[{ name:"1", status:"1" }, { name:"2", status:"1" }], '2':[{ name:"3", status:"2" }, { name:"4", status:"2" } ], '3':[ { name:"5", status:"3" }],'bbb':[{ name:"6", status:"bbb" }] }

用ES6如何把上面的变成下面这种结构.
不用一个一个 push,对每一个 status 直接 filter 一下就行了

let result = a.reduce((acc, {status}) => (
  acc[status] ? acc: {
    ...acc,
    [status]: a.filter(item => item.status === status)
  }
), {})

图片描述

图片描述

ramda

常见数组utils

export function delFromArr (val, arr) {
  if (arr && arr.indexOf(val) !== -1) {
    arr.splice(arr.indexOf(val), 1)
  }
}

export function clearArr (...arrs) {
  arrs && arrs.forEach(arr => arr.splice(0, arr.length))
}

/**
 * key: 'val'
 * arr: [{val: 1}, {val: 2}]
 * return [1, 2]
 */
export function getKeyMap (key, arr) {
  return arr.map(i => {
    return i[key]
  })
}

/**
 * key: 'val'
 * arr: [{val: 1}, {val: 2}]
 * return 2
 */
export function getMax (key, arr) {
  let result = arr.reduce((pre, next) => {
    return parseInt(pre[key]) > parseInt(next[key]) ? pre : next
  })

  return result[key]
}

export function arrDelObj (arr, key, val) {
  if (!(arr && key && val)) {
    console.error('arrDelObj error: arr, key or val is undefined')
  }
  return arr.filter(item => {
    return item[key] !== val
  })
}

图片描述
图片描述

特异性数据处理

每个菜鸟前端都会遇到一个菜鸟后端督促你学习数据处理,下面罗列一些遇到过的数据处理.

归一化下面数据,变成想要的格式

接口数据:
clipboard.png
前端想要的数据:

clipboard.png

实现:

图片描述

clipboard.png

clipboard.png

clipboard.png

降维、去重、排序
给出:let arr = [[1, 2, 3], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10, 0];
需求:降维、去重、排序
做法:Array.from(new Set(arr.flat(Infinity).sort((a, b) => a - b)))


解析如下:
0. arr.flat(Infinity)  //直接降维值一维数组。
1. sort     //排序就不说了。
2. new Set()  //达到去重效果
3. Array.from(上一步输出的结果)  //将上一步结果转换为数组

降维

Array.prototype.concat.apply([], arr)为啥这个方法会把数组的深度降 1 呢?

arr=[[1,2],3,4]。arr是一个二维数组,通过apply方法,apply方法第二个参数是arguments,即参数数组,前面的公式就变成了[].concat([1,2],[3,4],[5]),concat方法的参数是一个元素,该元素会被直接插入到新数组中;如果参数是一个数组,该数组的各个元素将被插入到新数组中;于是最后的结果就是[1,2,3,4,5]相当于把原来的二维数组拉成了一纬数组

给对象包裹一个[]

图片描述
图片描述

快速删除某个数组元素

image.png

参考

JS数组学习笔记
Array MDN
《数据结构与算法javascript描述》
JavaScript30-Challenge/04 - Array Cardio Day 1/
ES6,Array.from()函数的用法
《javascript经典实例》
Array.prototype.slice()
Array.prototype.forEach()
Array.prototype.map()
ES6的新方法实现数组去重
d3-array
lodash
d3-array 解释
https://segmentfault.com/q/10...
d3array 测试
JavaScript数组方法速查手册极简版

白鲸鱼
1k 声望110 粉丝

方寸湛蓝