js算法

提高性能的点

  • 对象尽量使用es6解构方式,尽量少的去访问引用类型
  • 不要过多频繁的使用push,会影响性能

数组去重

  1. 两个循环判断

判断问题:拿第一个和每一个去做比较,所以需要用到两个循环;

(1)写两个循环,第一个循环数组第一个数据,第二个循环让每一个和第一个做比较。

(2)第二循环j=i+1,再判断第二个循环的下标是否和第一个循环的下标的字符相同,如果是相同的,则删除一个

(3)删除之后数组变短,让j减一,重新做比较。

for(var i=0;i<ary.length;i++){
    for(var k=i+1;k<ary.length;k++){ 
        if(ary[i] === ary[k]){
            if(i == k){  //如果k等于0,则需要这一步
                continue;
            }
            ary.splice(k,1);
            k--; 
            //前面删除一个之后数组的长度会进1,此时的k会直接跳到循环去加1,让k减1;
        }
    }
}
  1. 使用set去重
Array.from(new Set([1,2,2,3])
  1. 使用reduce去重
let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((pre,cur)=>{
    if(!pre.includes(cur)){
      return pre.concat(cur)
    }else{
      return pre
    }
},[])
  1. 使用filter去重;
function unique (array) {
  var str = '';
  return array.filter(item=>{
    //利用filter过滤返回true的情况;
      // 判断字符串中有没有,如果有,则return;
    if (str.includes(typeof item + item)) return  
    return str += (typeof item + item)  // 如果没有,则存入,返回true;
  })
}

数组乱序

  1. 原地洗牌,不需要声明额外的数组从而更加节约内存占用率,

原理:依次遍历数组的元素,将当前元素和之后的所有元素中随机选取一个,进行交换

function shuffle(arr){
    for(let i=0;i<arr.length;i++){
        // 由于下标从0开始,length从1开始因此使用floor向下取整;
        let index= i + Math.floor(Math.random()*arr.length);
        [arr[i],arr[index]] = [arr[index],arr[i]]// 这里使用了es6的交换位置方法
    }
    return arr
}   // 传入一个数组则乱序
  1. 非原地洗牌
function sort2(arr){
  let arr2 = []
  while(arr.length){
    // arr的长度会越来越少; 实现随机生成的乱序;
    let index = Math.floor(Math.random()*arr.length)
    arr2.push(arr.splice(index,1)[0])
  }
  return arr2
}
  1. 使用sort进行乱序
let sort2 = arr => arr.sort(()=>Math.random() - 0.5)

数组排序

  1. 选择数组排序

判断问题:拿第一个和每一个去做比较,如果大于第二个,则让第一个到第二个位置去;

(1)写两个循环,第二个循环j=i+1;,不比较本身。

(2)判断数组的第一个字符i是否大于数组的第二个j字符,如果大于第一个字符,则调换位置。

  1. 冒泡数组排序
for(var i=0;i<ary.length;i++){
    for(var k=0;k<ary.length;k++){
        if(ary[k] > ary[k+1]){ //2k > 1n 1n 2k
            var n=ary[k];
            ary[k]=ary[k+1];
            ary[k+1]=n;
        } //自身和紧挨着的后一个比较;
    }
}
  1. sort()排序
arr.sort();
从大到小==>  arr.sort((a,b)=>b-a)

对象拷贝方法

浅拷贝:...扩展运算符浅拷贝;

var obj = {a:'haha',b:{c:'haha'}}
var obj2 = {...obj}
obj.b.c = 'lalala'
console.log(obj2.b.c)   // 'lalala'

深拷贝:

  1. JSON方法
let obj = {name: 'zs',age:18}
let obj2 = JSON.parse(JSON.stringify(obj))
obj2.name = 'ww'
  1. jquery深拷贝
var obj2 = $.extend(true,{},obj3)
  1. 浅拷贝+递归
// 第二个参数可传可不传;
function deepClone(origin,target={}){
    for(let prop in origin){
        // 不拷贝原型上的内容;
        if(origin.hasOwnProperty(prop){
            // 判断该值还是不是一个对象;
            if(typeof origin[prop] === 'object'){
                // 判断一下类型,并进行拷贝;
                target[prop] = Array.isArray(origin[prop]) ? [] : {}
                deepClone(origin[prop],target[prop])
            } else {
                target[prop] = origin[prop]
            }
        }
    }
    return target
}

对象合并

  1. jquery
var obj2 = $.extend({},obj1,obj3,obj4)
  1. vue中
vm.userPro = Object.assign({},obj1,obj2)

扁平化数组

  1. reduce
let arr = [1,2,[3,4,[5,6]]]
function fn(arr){
    return arr.reduce((p,c)=>{
        return p.concat(Array.isArray(c)?fn(c):c)
    },[])
}
fn(arr) // [1,2,3,4,5,6]
  1. toStringsplit方法,仅对数字有效
let arr = [1,2,[3,4,[5,6]]]
let arr2 = JSON.parse(`[${arr.toString()}]`)
  1. 使用递归遍历
let arr = [1,2,[3,4,[5,6]]]
function fn(arr){
    let res = []
    arr.map(item=>{
        if(Array.isArray(item){
            res = res.concat(fn(item))  // 将调用的结果合并
        }
        res.push(item)
    })
    return res
}
  1. flat() 括号里面传入数字,表示扁平化几个,当传入Infinity时,会扁平所有的数组;
var arr = [1[,2,3,[4,5,6]]]
arr.flat(Infinity)
  1. 使用...扩展运算符,最实用的一个方法
let arr = [1,2,[{name:'h'},[{age:18}]]]
while(arr.some(Array.isArray)){
    arr = [].concat(...arr)
}
console.log(arr)