欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

javascript 对象类型之 - Array

程序员文章站 2022-03-05 13:52:36
...

概述

var arr = [] ;
typeof arr; // 'object'

创建方式

// 1.字面量式
var arr1 = []; 
var arr2 = [1,2,3]; 

// 2.构造式
var arr3 = new Array(); // []
var arr4 = new Array(1,2,3); // [1,2,3]

var arr5 = new Array(3); // 
// 打印 3 次 undefined
for(var i=0;i<arr5.length;i++){
    consoel.log(arr5[i])
}
// 一次都不打印, 类似的还有 map ,every 等
arr5.forEach(item=>{
    console.log(1);
    console.log(item);
})

// 3. 具备 length 属性的伪数组通过 Array.from 转换
// 3-1
var str = '1234'
var arr6 = Array.from(str); // ['1','2','3','4']

// 3-2
var aLis = document.getElementsByTagName('li');
var aLis2 = Array.from(aLis);

// 3-3
function test(a,b,c){
    var args = Array.from(arguments);
}

// 3-4
var obj = {1:1,2:2,a:1,length:5}
Array.from(obj); // [undefined,1,2,undefined,undefined]

判断是否是数组

// 1. Array.isArray
var arr = []
Array.isArray(arr); // true

// 2. 
var isArray = (obj) => Object.prototype.toString.call(obj) === '[object Array]';
isArray(arr);

数组的基本方法

基本方法之 - 查找
  • indexOf => 元素所在的索引 || -1
var arr =[1,2,3,4,5]
var index = arr.indexOf(3); // 2
var index2 = arr.indexOf(10); // -1

// 判断是否在函数中 => Boolean
var isInArr = (val,arr)=>arr.indexOf(val) !== -1 ;
  • includes ,数组中是否包含元素 ; => Boolean
var arr = [1,2,3,4,5]
var hasFive = arr.includes(5); // true
var hasSix = arr.includes(6); // false
  • find ,找到第一个直接返回该元素; 遍历完整个数组未找到, 返回 undefined => ArrayItem || undefined
var arr = ['x','xx','xxx','xxxx']
var result = arr.find(item=>{
    console.log('loop'); 
    return item.length>2;
})
// 以上, 仅打印 3 次 'loop', 则说明提前中断了遍历返回, 最后返回 'xxx'

var result2 = arr.find(item=>{
    console.log('loop');
    return item.length>4;
})
result2; // undefined
  • findIndex 找到满足条件的位置索引, 提前找到符合条件的, 提前返回 , 结束整个迭代 ; 迭代完整个数组未找到则返回 -1 => arrayItemIndex || -1
var arr = ['x','xx','xxx','xxxx']
var result = arr.findIndex(item=>{
    console.log('loop'); 
    return item.length>2;
})
// 以上, 仅打印 3 次 'loop', 则说明提前中断了遍历返回, 最后返回 2

var result2 = arr.findIndex(item=>{
    console.log('loop');
    return item.length>4;
})
result2; // -1
基本方法之 - 操作
对原数组无影响
  • join , 将数组元素用特定的字符( 默认为逗号)拼接成字符串 => String
var arr = [1,2,3,4]

var str1 = arr.join(); 
console.log(str1); // '1,2,3,4'

var str2 = arr.join('&');
console.log(str2); // '1&2&3&4'
  • concat; 合并多个数组或元素 => Array

参数可为数组 , 多个数组, 单个元素, 多个单个元素. 单个元素和数组混杂

var arr = [1,2,3,4]
var arr2 = [5,6,7,8]

var mergeArr = arr.concat(arr2); 
console.log(mergeArr); // [1,2,3,4,5,6,7,8]

var newArr1 = arr.concat(5); // [1,2,3,4,5]
var newArr2 = arr.concat([5]);  // [1,2,3,4,5]
var newArr3 = arr.concat(5,6,7); // [1,2,3,4,5,6,7]
var newArr4 = arr.concat([5],[6,7]); // [1,2,3,4,5,6,7]
var newArr5 = arr.concat(5,[6,7]); // [1,2,3,4,5,6,7]

// 扩展符类似 concat 
var newArr6 = [...arr,5,6,7]; // [1,2,3,4,5,6,7]
  • slice(startIndex,endIndex), 从原数组拷贝一份下来, 从startIndex 开始(包括) 到 endIndex 结束( 不包括) => Array
var arr = ['x','xx','xxx','xxxx','xxxxx']
arr.slice(3); // ['xxxx','xxxxx']
arr.slice(3,3); // []
arr.slice(3,4); // ['xxxx']
对原数组有影响

直接在原数组上操作的方法, 会改变原数组的元素.

  • sort , 排序, 返回排序后的数组 => Array
// 1.正序
var arr = [1,9,3,2,5,8]
arr.sort(); // [1, 2, 3, 5, 8, 9]

// 或
var arr2 = [1,9,3,2,5,8]
arr2.sort((a,b)=>a-b); // [1, 2, 3, 5, 8, 9]

// 2.倒序
var arr3 = [1,9,3,2,5,8]
arr3.sort((a,b)=>b-a); // [9, 8, 5, 3, 2, 1]
  • push , 往数组元素的末尾添加元素, 返回新数组长度 => Array.length
var arr = [1,2,3]
arr.push(4); // 4
arr.push(5,6); // 6
arr.push(...[7,8]); // 8
console.log(arr); // [1,2,3,4,5,6,7,8]
  • unshift, 往数组元素的首端添加元素, 返回新数组长度 => Array.length
var arr = [1,2,3];
arr.unshift(0); // 4
arr.unshift(-2,-1); // 6
arr.unshift(...[-4,-3]); // 8
console.log(arr); // [-4, -3, -2, -1, 0, 1, 2, 3]
  • pop, 从数组末端删除一个元素, 返回被删除的元素 => ArrayItem
var arr = ['a','b','c','d']
arr.pop(); // 'd'
arr.pop(); // 'c'
console.log(arr); // ['a','b']
  • shift , 从数组首端删除一个元素, 返回刚删除的元素 => ArrayItem
var arr = ['a','b','c','d']
arr.shift(); // 'a'
arr.shift(); // 'b'
console.log(arr); // ['c','d']
  • reverse, 数组反向, 返回反向后的数组 => Array
var arr = [1,2,3,4]
arr.reverse();
console.log(arr); // [4,3,2,1]
  • splice(startIndex,num); 从原数组上切割下来一块, 返回切割下来的一块 => Array
var arr = ['x','xx','xxx','xxxx','xxxxx']
arr.splice(); // []

// 只一个参数时, 表示从开始位置切割到最后位置
var arr2 = ['x','xx','xxx','xxxx','xxxxx']
arr2.splice(0); // ['x','xx','xxx','xxxx','xxxxx']

// 两个参数, 表示从 startIndex 切割 num 个元素.
var arr3 = ['x','xx','xxx','xxxx','xxxxx']
arr3.splice(1,0); // []
arr3.splice(1,1); // ['xx']

// 三个或三个以上参数, 表示从切开位置, 填入新元素
var arr4 = ['x','xx','xxx','xxxx','xxxxx']
arr4.splice(1,1,'hello','hi'); //  ["x", "hello", "hi", "xxx", "xxxx", "xxxxx"]
基本方法之 - 迭代

类型转换

  • 其他转数组
// 1. 字符串转数组
var str1 = '1,2,3,4'
var arr1 = str1.split(',');

// 2. json 对象转数组, 对象必须有 length 属性, 会忽略键名非数字项
var obj = {1:1,0:2,a:1,length:5};
var arr2 = Array.from(obj);
  • 数组转其他
// 1. 数组转字符串 join
var arr1 = ['a','b','c','d']

// 1-1 默认合并字符为 , 
var str1 = arr1.join(); // 'a,b,c,d'

// 1-2 自定义合并字符
var str2 = arr1.join('-');
console.log(str2) ;// 'a-b-c-d'

数组应用

  • 遍历多维数组
var arr = [1,[2,[3,[4,[5]]]]];
function deepForEach(arr, fn) {
  arr.forEach(item => Array.isArray(item) 
                              ? deepForEach(item, fn) 
                              : fn(item))
}

deepForEach(arr, item => {
  console.log(item)
})
  • 展平多维数组
// 常规解法
var arr = [1,[2,[3,[4,[5]]]]];
function flatten(arr, result = []) {
  for (var i = 0; i < arr.length; i++) {
    if (Array.isArray(arr[i])) {
      flatten(arr[i], result);
    }
    else {
      result.push(arr[i])
    }
  }
  return result;
}

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

// 换种写法
function flatten(arr) {
  var result = [];
  for (var i = 0; i < arr.length; i++) {
    result = result.concat(Array.isArray(arr[i]) ? flatten(arr[i]) : arr[i])
  }
  return result;
}

// reduce 解法
var flatten = (arr) => arr.reduce((prev, now) => {
  return prev.concat(Array.isArray(now) ? flatten(now) : now)
}, []);

flatten(arr); 
  • 树形结构
var originData = [
  { title: '标题1', id: '1', pid: '0' },
  { title: '标题1-1', id: '1-1', pid: '1' },
  { title: '标题1-2', id: '1-2', pid: '1' },
  { title: '标题2', id: '2', pid: '0' },
  { title: '标题2-1', id: '2-1', pid: '2' },
  { title: '标题2-2', id: '2-2', pid: '2' },
  { title: '标题2-1-1', id: '2-1-1', pid: '2-1' },
  { title: '标题2-2-1', id: '2-2-1', pid: '2-2' },
  { title: '标题2-2-2', id: '2-2-2', pid: '2-2' },
  { title: '标题2-2-2-1', id: '2-2-2-1', pid: '2-2-2' },
  { title: '标题2-2-2-2', id: '2-2-2-2', pid: '2-2-2' },
];

// 常规
function toTree(arr, pid) {
  var treeArr = [];
  var allTreeLeaf = arr.filter(item => item.pid === pid);
  allTreeLeaf.forEach(tree => {
    let _children = toTree(arr, tree.id)
    if (_children.length) {
      tree.children = _children;
    }
    treeArr.push(tree);
  })
  return treeArr;
}

var formatTree = toTree(originData,'0');

// 将树形展平还原回去
function flattenTree(treeData, linkKey) {
  var result = [];
  treeData.forEach(thrunk => {
    if (thrunk[linkKey] && thrunk[linkKey].length) {
      result = result.concat(flattenTree(thrunk.children, linkKey))
    }
    delete thrunk[linkKey]
    result = result.concat(thrunk);
  })
  return result;
}

console.log(flattenTree(formatTree, 'children'))
  • 求数组中最大值
// 1. 常规
function getMax(arr){
    var max = arr[0]
    arr.forEach(item=>{
        max = item>max? item:max;
    })
    return max;
}

// 2.常规用 reduce 变式
function getMax(arr) {
  return arr.reduce((prev, now) => Math.max(prev,now))
}

// 3. max 直接求最大, 好吧, max 是可以传多个参数的
var getMax = (arr)=>Math.max(...arr);

// 4. 先排序,再末尾元素值 => 副作用, 在原数组的操作, 会影响原数组,鸡肋
var getMax = (arr)=>arr.sort((a,b)=>b-a)[0];
var getMax = (arr)=>arr.sort().reverse()[0];

// 5. 利用对象的键名自动排序原理
function getMax(arr){
    var obj = {}
    arr.forEach((item)=>{
        obj[item] = item;
    });
    var keys = Object.keys(obj);
    return Number(keys[keys.length-1]);
}

最简直的还是直接用 Math.max(...arr)

  • 数组去重
var arr = [1,3,4,2,3,5,12,5]
// 1. 常规, => for 式
function unique1(arr){
    var uniqueArr = []
    arr.forEach(item=>{
        if(!uniqueArr.includes(item)){
            uniqueArr.push(item);
        }
    })
    return uniqueArr
}

// 2. 对象键名不可重复性, => obj 式
function unique2(arr){
    var obj = {}
    arr.forEach(item=>{
        obj[item] = item
    })
    return Object.values(obj);
}

console.log(unique(arr))

// 3. Set
var unique3 = (arr)=>[...new Set(arr)]

// 4. Map , 和方法 2 的用对象转换类似
// 原理解释 : 如果 map 里面已经有该键, 则返回false ; 如果没有 则设置该键, 并且返回true; filter 接收到这个true , 把它添加到结果数组中.
function unique4(arr){
   var tmp = new Map();
   return arr.filter(item => {
       return !tmp.has(item) && tmp.set(item, 1);
   })
}

// 5. json 对象的类似 Map 解法 , => obj-map 式
function unique5(arr){
    var obj = {}
    return arr.filter(item=>{
        return !obj[item] && Object.assign(obj,{[item]:''})
    })
}

时间效率上: Set > Map > obj 式 > obj-map 式 > for 式

javascript 对象类型之 - Array