【关于Javascript】--- 数组篇(含ES6)

Jerry

创建 读取

var arr = [];
var arr2 = new Array(); 
var arr2 = new Array(3);//创建了一个长度为3的数组对象
var arr = new Array(2,1);//相当于创建了[2,1] 不常用

------------
var arr = [1];
arr.length = 3; //长度变3 后两个的值是undefined 不常用

var arr2 = [5, 4, 3, 2, 1];
arr2.length = 2; //长度变2
console.log(arr2) //输出[5, 4]   不常用

------------
var arr3 = [3,4,5];
console.log(arr3[1]) //输出4 下标 
console.log(arr3.length) //3 数组长度
注意一下两种情况:
  • 数组直接量的语法允许有可选的结尾的逗号。结尾如果多且只多一个逗号不影响数组长度 故例子1输出是2 但例子2的输出是3
  • 如果省略数组直接量中的某个值,省略的元素将被赋值undefined值
    //例子1:
    var arr = [,,];
    console.log(arr.length) //输出2 而不是3

    //例子2:
    var arr2 = [2,3,4,];
    console.log(arr2.length)//输出3

    var arr3 = [2,3,4,,]; 
    console.log(arr3.length)//输出4

    var arr4 = [2,,3]; //数组length是3
    console.log(arr4[1]) // undefined

检测数组

var arr = [];

typeof arr; //object typeof数组object和null都返回 object 

//instanceof 方法 能检测;
arr instanceof Array 

//最准确方法 利用原型 能检测;
Object.prototype.toString.call(arr) === "[object Array]";
Object.prototype.toString.call(arr).slice(8,-1) == "Array"


常用API

其中会修改原数组的有:
push pop shift unshift sort reverse splice

push:在数组后添加
pop:从数组后删除一个元素
shift:从数组前删除一个元素
unshift:在数组前添加
var arr = [1,2,3];
arr.push(4);//[1,2,3,4]
var arr2 = [1,2,3];~~~~
arr2.pop();//[1,2]

----------------

 var arr = [1,2,3];
 arr.shift(4);//[4,1,2,3]
 var arr2 = [1,2,3];
 arr2.unshift();//[2,3]
splice 替换 或新增 或删除

splice(起点A,长度B,插入数组的元素C);
直接修改原数组,另外会返回它删除的元素数组

1、从起点A开始计算B个长度,如果没有C,那么删除B个元素;
2、从起点A开始 如果没有B 没有C, 那么从起点开始删除到数组结尾元素
3、从起点A开始,长度B等于0,有C,那么从起点开始添加入C;如果B不等于0,那么 从起点开始删除B个元素,然后增加C(个数相同时就是 替换)

var arr = [1,2,3,4,5,6];
var deleteArr = arr.splice(2,3) //从位置2开始删除3位 》[3,4,5]
console.log(arr) // 输出[1,2,6]

------------
var arr = [1,2,3,4,5,6];
var deleteArr = arr.splice(2) //从位置2开始删除数组结尾元素 》[3,4,5,6]
console.log(arr) // 输出[1,2]

------------

var arr = [1,2,3,4,5,6];
var deleteArr = arr.splice(2,0,"a","b") //从位置2开始删除数组结尾元素 》[]
console.log(arr) // 输出[1,2,"a","b",3,4,5,6]

------------

var arr = [1,2,3,4,5,6];
var deleteArr = arr.splice(2,2,"a","b") //从位置2开始删除数组结尾元素 》[3,4]
console.log(arr) // 输出[1,2,"a","b",5,6]
sort 排序

排序:先0-9 然后A-Za-z的排 先大写后小写;


var arr = [1,3,12,4,15,6,0,12];
arr.sort(); //输出[0, 1, 12, 12, 15, 3, 4, 6]

------------

所以数字排序需要再函数处理一下
var arr = [1,3,12,4,15,6,0,12];
arr.sort(function(a,b){
    return a-b;//大到小的排
    //return a-b;//小到大的排
}); //输出[0, 1, 3, 4, 6, 12, 12, 15]

reverse 反转
var arr = [1,2,3];
arr.reverse();//[3,2,1]

字符串的反转:
"237892heLLo3我是中国人".toLowerCase().split('').reverse().join("");

?------ 以上操作修改原数组的 ------- ?

slice 分隔数组 不影响原数组

slice(起点A,个数B);
1.起点A开始截取B个数
2.B==0时,从起点A截取到数组结尾元素
如果参数出现负数,是它相对于数组中最后一个元素的位置 即到数第几个

var arr = [1,2,3,4,5,6,7];
arr.slice(0,3); // 起点0开始[1,2,3]
arr.slice(3); // 起点到数组结尾元素 [4,5,6,7]
arr.slice(1,-1)//从1到倒数第1位的区间 [2,3,4,5,6]
arr.slice(-4,-1)//从倒数第4位到倒数第1位的区间 [4,5,6]
concat 将数组拼接并
var arr = [1,2,3];
arr.concat(["a","b"]); //[1, 2, 3, "a", "b"];
arr.concat([4,5],[6,7]); //[1,2,3,4,5,6,7];
arr.concat(4,[5,[6,7]]); //[1,2,3,4,5,[6,7]];

split:字符串转换数组 join:数组转换成字符串
var str = "12683";
var arr = str.split(''); // ["1", "2", "6", "8", "3"]
arr.join('-'); //"1-2-6-8-3"

------ 以下是Es5的数组方法 -------

forEach 遍历所有元素
//forEach  
var arr = [1,2,3];
arr.forEach(function(item, index){
    console.log(index, item)//遍历数组所有的元素  
})
every 判断所有元素是否都符合条件
//every
var arr = [1,2,3];
var result = arr.every(function(item, index){
    return item < 4
})
console.log(result) //得到一个布尔值 都符合条件 所以true
some 判断是否至少有一个元素符合条件
//some
var arr = [1,2,3];
var result = arr.some(function(item, index){
    return item > 2 
})
console.log(result) //得到一个布尔值 只要有一个元素符合条件 大于2 所以true
map 遍历并有返回 类似forEach
//map  遍历 
var arr = [1,2,3,4];
var newArr = [];
newArr = arr.map(function(item,index){
    return '<b>' + item + '</b>';
})

console.log('arr',arr) //[1, 2, 3, 4]
console.log('newArr',newArr) //["<b>1</b>", "<b>2</b>", "<b>3</b>", "<b>4</b>”]
filter 过滤
//filter  
var arr = [1,2,3,4];
var newArr = arr.filter(function(item,index){
    //符合条件 true的被留下
    return item >= 2;
})
console.log('arr',arr)  //[1, 2, 3, 4]
console.log('newArr',newArr) //[2,3,4]
reduce 累加

reduce(function(sum,item){},base)
sum是累加值,item是元素值,base是可以额外增加的参数 可不传;
输出结果 总数 初始值base 加|乘|除|拼接后续的参数;

var arr = [1,2,3];
arr.reduce(function(sum,item){
    console.log(sum,item)
    return sum+item;
},100)
//100+1+2+3 > >106

------------

var arr = [1,2,3];
arr.reduce(function(sum,item){
    console.log(sum,item)
    return sum*item;
},4)
//4* 1*2*3  > >24

------------

[[0, 1], [2, 3]].reduce(
  (acc, cur) => {
    return acc.concat(cur)
  },
  [1, 2]
)
//输出 1,2,0,1,2,3
indexOf 查找并返回位置 没有返回-1
var arr = [12,3,4,56,57,23];
arr.indexOf(56) // 3
arr.indexOf(58) //-1

ES6扩展

扩展运算符 三个点(...
  • 该运算符主要用于函数调用
  • 扩展运算符与正常的函数参数可以结合使用,非常灵活。
  • 扩展运算符后面还可以放置表达式。
  • 如果扩展运算符后面是一个空数组,则不产生任何效果。
  • 注意,只有函数调用时,扩展运算符才可以放在圆括号中,否则会报错
  • 替代函数的 apply 方法
console.log(...[1, 2, 3])// 1 2 3
console.log(1, ...[2, 3, 4], 5)// 1 2 3 4 5
[...document.querySelectorAll('div')]// [<div>, <div>, <div>]

**该运算符主要用于函数调用
function push(array, ...items) {
  array.push(...items);
}

function add(x, y) {
  return x + y;
}

const numbers = [4, 38];
add(...numbers) // 42 把数组格式的numbers展开传进去

**扩展运算符与正常的函数参数可以结合使用,非常灵活。
function f(v, w, x, y, z) { }
const args = [0, 1];
f(-1, ...args, 2, ...[3]);

**扩展运算符后面还可以放置表达式。
const arr = [
  ...(x > 0 ? ['a'] : []),
  'b',
];

**如果扩展运算符后面是一个空数组,则不产生任何效果。
[...[], 1]// [1]

**注意,只有函数调用时,扩展运算符才可以放在圆括号中,否则会报错
(...[1, 2])// Uncaught SyntaxError: Unexpected number

console.log((...[1, 2]))// Uncaught SyntaxError: Unexpected number

console.log(...[1, 2])// 1 2

**替代函数的 apply 方法
var arr = [4,5,3,2,7,1,9];
Math.max.apply(null,arr);//9; Es5时的方法
Math.max(...arr); //9; Es6利用扩展符
// 等同于
Math.max(4,5,3,2,7,1,9);

//另一个例子是通过`push`函数,将一个数组添加到另一个数组的尾部。
// ES5的 写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);

// ES6 的写法
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);

扩展运算符的应用:
(1)复制数组

const a1 = [1, 2];const a2 = a1;
a2[0] = 2;
a1 // [2, 2] 数组是复合的数据类型,直接复制的话,只是复制了指向底层数据结构的指针,而不是克隆一个全新的数组
  
  -----------
  
**ES5 只能用变通方法来复制数组
const a1 = [1, 2];
const a2 = a1.concat(); 

a2[0] = 2;
a1 // [1, 2]  
上面代码中,`a1`会返回原数组的克隆,再修改`a2`就不会对`a1`产生影响。

  -----------
** Es6扩展运算符提供了复制数组的简便写法
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
上面的两种写法,`a2`都是`a1`的克隆。

(2)合并数组

const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合并数组 浅拷贝
arr1.concat(arr2, arr3);// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并数组 浅拷贝
[...arr1, ...arr2, ...arr3] // [ 'a', 'b', 'c', 'd', 'e' ]

(3)与解构赋值结合

const list = [23,44,55,99]
// ES5  赋值 a 23   rest [44, 55, 99]
a = list[0], rest = list.slice(1)
// ES6  赋值 a 23   rest [44, 55, 99]
[a, ...rest] = list

const [first, ...rest] = [];
 //  first> undefined ; rest > []

const [first, ...rest] = ["foo"];
//  first> "foo" ; rest > []

**如果将`扩展运算符用于数组赋值`,只能放在参数的最后一位,否则会报错。
const [...butLast, last] = [1, 2, 3, 4, 5];// 报错

const [first, ...middle, last] = [1, 2, 3, 4, 5];// 报错

(4)字符串

*扩展运算符还可以将字符串转为真正的数组。
[...'hello']// [ "h", "e", "l", "l", "o" ]

*能够正确识别四个字节的 Unicode 字符。
'x\uD83D\uDE80y'.length // 4
[...'x\uD83D\uDE80y'].length // 3

(5)实现了 Iterator 接口的对象

let nodeList = document.querySelectorAll('div');
let array = [...nodeList];
扩展运算符可以将其转为真正的数组,原因就在于`NodeList`对象实现了 Iterator

(6)Map 和 Set 结构,Generator 函数

  • 扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构。
  • Generator 函数运行后,返回一个遍历器对象,因此也可以使用扩展运算符。
let map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);

let arr = [...map.keys()]; // [1, 2, 3]
----------
const go = function*(){
  yield 1;
  yield 2;
  yield 3;
};

[...go()] // [1, 2, 3] 变量`go`是一个 Generator 函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值,转为一个数组。
Array.from() 将两类对象转为真正的数组 接受3种参
  • Array.from (obj, mapFn) //对象 , 函数
  • Array.from(string) //字符串打散成数组
  • Array.from ({length:n}, mapFn) //数组长度,函数返回设定数组每一位的值
`Array.from (obj, mapFn)`
//对象
    let arrayLike = {
        '0': 'a',
        '1': 'b',
        '2': 'c',
        length: 3
    };
    // ES5的写法
    var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c'] 相当于var arr1 = Array.prototype.slice.call(arrayLike); 
    // ES6的写法
    let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
    
    let namesSet = new Set(['a', 'b']);//建一个对象 {"a", "b"}
    Array.from(namesSet) // ['a', 'b'] 把对象转字符串

------------

// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).forEach(function (p) {
  console.log(p);
});

// 相当于
[...document.querySelectorAll('div')]

------------

// arguments对象
function foo() {
    console.log('arguments',arguments);//arguments 
    var args = Array.from(arguments); // 相当于var args = [...arguments];
    console.log(args);  //数组[3, 2, 5, 2, 1]
}
foo(3,2,5,2,1); 

let arrayLike = { '0': '2', '1': '4', '2': '5', length: 3 }
Array.from(arrayLike, x => x*2) //[4,8,10]

------------
`字符串 Array.from(string)`
Array.from('我是学生');//["我", "是", "学", "生"];
'我是学生'.split("");//["我", "是", "学", "生"];

Array.from({length:2}, () => 'jack') //["jack", "jack"]
Array.from({length:2}, item => (item = {'name':'shao','age':18})) //[{'name':'shao','age':18},{'name':'shao','age':18}]
Array.from({length: 2}, (v, i) => item = {key:i*2});//[{key:0},{key:2}]


------------
`Array.from ({length:n}, mapFn)`
Array.from({ length:  3  });//创建一个长度为3的数组,值都是undefined [ undefined, undefined, undefined ]
------------
//数组 返回数组本身
Array.from([1, 2, 3])// [1, 2, 3]
Array.of() 方法用于将一组值,转换为数组
Array.of(3, 11, 8) // [3,11,8]
Array.of() // []
Array.of(undefined) // [undefined]
数组实例的copyWithin(target,start,end)

三个参数

  • target(必需):从该位置开始替换数据。
  • start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
  • end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
上面代码表示将从3号位直到数组结束的成员(4和5),复制到从0号位开始的位置,结果覆盖了原来的1和2。

// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]

// 将3号位复制到0号位
[].copyWithin.call({length: 5, 3: 1}, 0, 3)
// {0: 1, 3: 1, length: 5}

// 将2号位到数组结束,复制到0号位
var i32a = new Int32Array([1, 2, 3, 4, 5]);
i32a.copyWithin(0, 2);
// Int32Array [3, 4, 5, 4, 5]

// 对于没有部署TypedArray的copyWithin方法的平台
// 需要采用下面的写法
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]
数组实例的find()和findIndex() 找出第一个符合条件的数组成员。它的参数是一个回调函数
[1, 4, -5, 10].find((n) => n < 0)// -5

//find接受3个参数 value当前值 index当前index 原数组arr
[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10

`这两个方法都可以发现`NaN`,弥补了数组的`IndexOf`方法的不足。`
[NaN].indexOf(NaN)// -1
[NaN].findIndex(y => Object.is(NaN, y))// 0
数组实例的fill(value,start,end) 使用给定值,填充一个数组
  • value:填充的值
  • start:填充的起始位置
  • end: 填充的结束位置
['a', 'b', 'c'].fill(7)// [7, 7, 7]
new Array(3).fill(7)// [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2)// ['a', 7, 'c'] 从1号位开始,向原数组填充7,到2号位之前结束。
遍历数组: entries()、keys()和values()

keys()是对键名的遍历
values()是对键值的遍历
entries()是对键值对的遍历

//用`for...of`循环进行遍历
for (let index of ['a', 'b'].keys()) {
  console.log(index); // 0 1
}

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

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

//手动调用遍历器对象的`next`方法,进行遍历
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']
includes(value,position) 返回一个布尔值,表示某个数组是否包含value,与字符串的includes方法类似

Array.prototype.includes()

  • value:查找的值
  • position:开始查找的位置,默认0;若为负数表示倒数第几个
[1, 2, 3].includes(3);     // true
[1, 2, 3].includes(4);     // false
[1, 2, NaN].includes(NaN); // true
[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true 
数组的空位 值数组的某一个位置没有任何值
//`Array`构造函数返回的数组都是空位
Array(3) // [, , ,]
0 in [, , ,] // false
0 in [undefined, undefined, undefined] // true

----------ES5对空位------------
*   `forEach()`,`filter()`,`every()`和`some()`都会跳过空位。
*   `map()`会跳过空位,但会保留这个值
*   `join()`和`toString()`会将空位视为`undefined`,而`undefined`和`null`会被处理成空字符串。
// forEach方法
[,'a'].forEach((x,i) => console.log(i)); // 1

// filter方法
['a',,'b'].filter(x => true) // ['a','b']

// every方法
[,'a'].every(x => x==='a') // true

// some方法
[,'a'].some(x => x !== 'a') // false

// map方法
[,'a'].map(x => 1) // [,1]

// join方法
[,'a',undefined,null].join('#') // "#a##"

// toString方法
[,'a',undefined,null].toString() // ",a,,"

----------ES6对空位------------
ES6则是明确将空位转为`undefined`

//`Array.from`方法会将数组的空位,转为`undefined`
Array.from(['a',,'b'])// [ "a", undefined, "b" ]

//扩展运算符(`...`)也会将空位转为`undefined`
[...['a',,'b']]// [ "a", undefined, "b" ]

// entries()
[...[,'a'].entries()] // [[0,undefined], [1,"a"]]

// keys()
[...[,'a'].keys()] // [0,1]

// values()
[...[,'a'].values()] // [undefined,"a"]

// find()
[,'a'].find(x => true) // undefined

// findIndex()
[,'a'].findIndex(x => true) // 0


//`copyWithin()`会连空位一起拷贝
[,'a','b',,].copyWithin(2,0) // [,"a",,"a"]

//fill()会将空位视为正常的数组位置
new Array(3).fill('a') // ["a","a","a"]

//`for...of`循环也会遍历空位
let arr = [, ,];
for (let i of arr) {
  console.log(1); // 1  1
}
数组实例的 flat(),flatMap() 用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。

flat(depth)
depth:降维深度,可设置默认是1;如果不知道嵌套了多少层,可传Infinity作为参数,就会降到1维

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

//如果原数组有空位,flat()方法会跳过空位
[1, 2, , 4, 5].flat()// [1, 2, 4, 5]

flatMap(vaule) 方法对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()
flatMap()只能展开一层数组

// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
[2, 3, 4].flatMap((x) => [x, x * 2])
// [2, 4, 3, 6, 4, 8]

//返回3个参数 当前数组成员、当前数组成员的位置(从零开始)、原数组
arr.flatMap(function callback(currentValue[, index[, array]]) {
  // ...
}[, thisArg])

对象和数组转化

var obj = {name:"tom",age:12,sex:"man"};

Object.keys(obj);//["name", "age", "sex"] 获取对象的key组合数组

Object.values(obj)//["tom", 12, "man"] 获取对象的value组合数组

Object.entries(obj)// 
[["name", "tom"],["age", 12], ["sex", "man"]]

常见题目

1.封装数组去重

方法一: 遍历 利用indexOf区分是不是初次出现添加在新数组
var arr = [1,3,4,6,3,2,1];

function unique1(arr){
    let newArr = [];
    arr.map(function(item,index){
        if(newArr.indexOf(item) == -1){
            newArr.push(item)
        }
    })
    return newArr;
}



--------------------------

方法二: 利用对象属性的存在的特性,如果没有该属性则存入数组
function unique2(str){
    let arrObj = {};
    let newArr = []; 
    for(var i=0;i<str.length;i++){
        if(!arrObj[str[i]]){
            arrObj[str[i]] = 1;
        }
    }
    for(key in arrObj){
        newArr.push(key);
    }
    return newArr;
}


--------------------------
方法三: 排序后相邻去重 思路:原数组排序,排序后相同值相邻,然后遍历时新数组只传入不与前一个值相同的值

function unique3(arr) {
    arr.sort(); //排序后arr已经改变了
    var res = [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== res[res.length - 1]) {
            res.push(arr[i])
        }
    }
    return res;
}
console.log(unique3(arr));


--------------------------

//方法四:ES6 Set数据结构类似于数组,其成员都是唯一的 IE系列不兼容
function unique4(arr) {
    // return Array.from(new Set(arr)) ;//Array.from 将Set结构转换成数组
    return [...(new Set(arr))]
}
console.log(unique6(arr))
    
    eg:const set = new Set([1, 1, 2, 3, 4]);
        console.log(set); //{1, 2, 3, 4}
        Array.from(set);//利用Array.from 转成数组[1,2,3,4]
        [...set]; //利用...转成数组[1,2,3,4]
--------------------------
//方法五:ES6
function unique5(arr) {
    const res = new Map();
    return arr.filter((a) => !res.has(a) && res.set(a, 1))
}
console.log(unique5(arr));
2.统计一个字符串中出现最多的字符
var str = 'sdksajweiskajdskhfkwjskdsd';

function countMax(str){
    let str_arr = str.split('');
    let countObj = {};
    for(var i=0;i<str_arr.length;i++){
        if(countObj[str_arr[i]]){
            countObj[str_arr[i]] ++;
        }else{
            countObj[str_arr[i]] = 1;
        }
    }

    var result_name ='',result_num=0; 
    for(key in countObj){
        if(countObj[key] > result_num){
            result_num = countObj[key];
            result_name = key;
        }
    }
    return result_name;
}

//思路:装在对象里 统计个数; 对象循环记录最大值;并返回
3.找出数组中的最大值
var arrMax = [1,2,3,4,5];
//1.for循环,古老的写法,遍历之后取最大值
var arrRes = arrMax[0];
for(var i = 1 ;i <arrMax.length; i++){
var result = Math.max(arrRes,arrMax[i])
}
console.log(result)
//2.Math最大值。用到apply方法,可以将数组转换成参数列表再调用Math方法
Math.max.apply(null,arrMax)
//3.sort()
arrMax.sort((num1,num2) => {return num2-num1})[0] //或者sort()后reverse()
//4.reduce()
arrMax.reduce((num1,num2) => {return num1 > num2 ? num1 : num2})
4.数组的浅拷贝和深拷贝
什么是浅拷贝:
var array1 = ['a',1,true,{name:'lei',age:18}];

//concat()  slice() 实现浅拷贝
var array2 = array1.concat()

//修改拷贝后的数据
array2[0] = 'b';            //array1[0]是原始数据类型 所以是直接赋值的
array2[3].name = 'zhang';   //array1[3]是对象数据类型 所以拷贝的是对象的引用,其实还是和原数组使用同一对象

console.log(array2);   // ['b',1,true,{name:'zhang',age:18}]
console.log(array1);   // ['a',1,true,{name:'zhang',age:18}]


array2是array1的浅拷贝对象,数组元素是原始数据类型的不会相互影响了(array1[0]),但是array1[3]是对象类型,还是会互相影响。
浅拷贝怎么做:
var arr1 = arr.concat(); //方法1 concat(),浅拷贝
var arr2 = arr.slice(0); //方法2 slice(),浅拷贝
-------------------------
ES6拓展运算符 \[...list\]
let arr = [1,2,3,4]
let list = [...arr]
list[0] = '111'
console.log(arr,list)

arr的打印结果:
[1, 2, 3, 4]

list的打印结果:
 ["111", 2, 3, 4]
-------------------------
var arr3 = []; //方法3 for循环,浅拷贝
for (var i in arr) {
    arr3[i] = arr[i]
}
深拷贝及其实现

从浅拷贝解释基本可以明白,深拷贝就是 ‘完全’拷贝,拷贝之后新旧数据完全分离,不再共用对象类型的属性值,不会互相影响

方法一:取巧方法 JSON.parse(),JSON.stringify()
该方法不能深拷贝属性值是函数的对象

let a = [{
    'aa': undefined,
    'bb': [1, 2, 3],
    'cc': null,
    'dd': () => {}
}]
let b = JSON.parse(JSON.stringify(a))
console.log(a, b)

a的打印结果: 
    aa:undefined
    bb:[1, 2, 3]
    cc:null
    dd:ƒ ee()

b的打印结果:
    bb:[1, 2, 3]
    cc:null
    
--------------------------

方法二: for循环
//实现深拷贝
function deepClone(arr) {
    var res = [];
    for (var i in arr) {
        if (typeof arr[i] === 'object') { //如果含有对象,则递归
            res[i] = deepClone(arr[i])
        } else {
            res[i] = arr[i]
        }
    }
    return res
}

//测试
var test = [1,'a',{name:'lei',age:18}];

var copy2 = deepCopy(test);
copy2[2].name = 'zhang';
console.log(test);  ////[1,'a',{name:'lei',age:18}]  未受到影响
5.数组降维
var arrDown = [[1, 2, 3],[4, 5],[9, 8, 7]];
var arrDown2 = [[1, 2, 3],[4, 5,[23,45]],[9, 8, 7,[12,34,[233]]]];

--------------------------------
方法一:遍历 push进新数组
function arr_fn(arr){
    let newArr =  [];
    function down(arr){
        for(let i = 0; i < arr.length; i ++){
          if(Array.isArray(arr[i])){
            down(arr[i])
          }else{
            newArr.push(arr[i]);
          }
        }
  }
    down(arr); //递归多维度处理
    return newArr;
}
console.log(arr_fn(arrDown))//[1, 2, 3, 4, 5, 9, 8, 7]
console.log(arr_fn(arrDown2))//[1, 2, 3, 4, 5, 23, 45, 9, 8, 7, 12, 34, 233]

--------------------------
方法二: concat() 
function down2(arr) {
    var resDown = [];
    for (var i = 0; i < arr.length; i++) {
        resDown = resDown.concat(arr[i])
    }
    return resDown
}
console.log(down2(arrDown))


--------------------------
方法三:concat()和apply()结合
function down3(arr) {
    var resDown = [];
    return Array.prototype.concat.apply(resDown, arr)
}
console.log(down3(arrDown))

--------------------------

基于以上方法二三没改成递归 所以也只能降一维度
console.log(down(arrDown))
》[1, 2, 3, 4, 5, 9, 8, 7]

console.log(down(arrDown2))
》[1, 2, 3,4, 5,[23,45],9, 8, 7,[12,34,[233]]]

未完待续。。。

来源链接:
https://www.jianshu.com/p/4db...
https://developer.mozilla.org...
Es6:https://www.w3cschool.cn/ecma...
Es6文档:http://caibaojian.com/es6/arr...
阮一峰Es6入门:https://es6.ruanyifeng.com/#d...

mark一下 仅供参考 欢迎更正补充 end

阅读 799

喈喱前端笔记
学习的付出 从不欺人

学习的付出 从不欺人。记忆总是苦,写总结最牢固

468 声望
198 粉丝
0 条评论
你知道吗?

学习的付出 从不欺人。记忆总是苦,写总结最牢固

468 声望
198 粉丝
宣传栏