前端小白 ( 持续更新记录JS语法技巧 )

293 阅读4分钟

记录在工作中可能会常用到的语法技巧

   Tips - (暂时不考虑兼容性)

last update : 2022年11月25日21:57:41

-----------main----------------

一、用at(-1) 替代arr.length-1

    
        let arr = [1, 2, 3, 4, 5];
        let lastLength = arr[arr.length - 1];
        // 简化 
        lastLength = arr.at(-1);

# 二、用?.代替&&运算符

       let obj = { name: '1' };
       let name = obj && obj.name;

       // 简化
       name = obj?.name;

三、使用arr.flat扁平化数组

       let arr = [1,2,3,4,[5,6,7,8,[9,10]]]
       
       //简化
       let flatArr =  arr.flat(Infinity); //传入Infinity可扁平二维以上数组

# 四、promise async await

       async fun(){
           let result = await promiseApi();
       }

# 五、Object.keys || Object.values

      let obj = {
            name: '1',
            arr: [1, 2, 3, 4]
        }
        let temp = [];

        //需要拿到obj的values || keys
        for (let k in obj) {
            temp.push(k)  //keys //temp.push(obj[k]) //values
        }
        
        //简化
        temp = Object.keys(obj);
        temp = Object.values(obj);

六、使用...语法糖 合并 || 解构

        let obj = { name: '1', TempArr: ['a', 'b', 'c', 'd'] }
        let obj1 = { age: '18' }

        //合并对象
        let assignObj = { ...obj, ...obj1 }


        let arr = [1, 2, 3, 4]
        let arr1 = [5, 6, 7, 8]
        //合并数组
        let assignArr = [...arr, ...arr1];

        //解构赋值
        let { TempArr } = obj;
        let [a, b, c, d] = TempArr;

# 七、数组去重

        let arr = [1, 2, 3, 4, 5, 4, 5, '4', '5'];
        //简化
        let unique = Array.from(new Set(arr))
        console.log(unique, 'unique 不会去除字符串4、5')

八、数组计算

        let arr = [1, 2, 3, 4, 5, 6, -100, 521];
        let max = Math.max(...arr);
        let min = Math.min(...arr);
        let count = arr.reduce((a,b) => a+b); //442
        console.log(max) //521
        console.log(min) //-100

九、replaceAll 全部替换

       let str = "Hi!,这是ES6~ES12的新特性,目前为ES12"
 
       console.log(str.replace("ES", "SY")); // Hi!,这是SY6~ES12的新特性,目前为ES12  
       console.log(str.replaceAll("ES", "Sy")); // Hi!,这是Sy6~Sy12的新特性,目前为Sy12 

十、对象映射改造干掉IF SWITCH

        function fun(type) {
            // 假如有这样一段代码
            if (type === "success") {
                return "green";
            }
            if (type === "warning") {
                return "yellow";
            }
            if (type === "error") {
                return "red";
            }

            // switch改造
            switch (type) {
                case "success":
                    return "green";
                case "warning":
                    return "yellow";
                case "error":
                    return "red";
            }

            // 对象映射改造 
            const typeMap = {
                success: "green",
                warning: "yellow",
                error: "red",
            };
            //如果需要默认值可以用??运算符 比如 typeMap['ok'] 没有的话 会返回??后的内容
            return  typeMap[type]??'默认值';
        }

十一、多维数组扁平化(递归方式)

 const multipleArr = [[1, 2, 3],[4, 5, 6],[7, 8, 9],[10, [11, [12, [13]]]]]

        function flatArr(data, r = []) {
            data.map(x => {
                if (Array.isArray(x) && x.length) {
                    flatArr(x, r);
                } else {
                    r.push(x);
                }
            })
            return r;
        }
        
        let fArr = flatArr(multipleArr)
  

十二、数组转Tree(递归)

    function toTree(data, nodeId = 0, r = []) {
        // 判断arr是否是数组
        if (!Array.isArray(data)) return []
        data.map(x => (x.pid === nodeId) && r.push({ ...x, children: toTree(data, x.id) }));
        return r;
    }

    let r = toTree(arr);

十三、数组转Tree(map对象 + 循环 性能对比递归更好)

/* 转map再进行数据查找 可控制对比的键名是 key 还是 id  pid 传字符串 比如有的数据是parentId  */
arrayToTree(arr, keyPath = 'key', pid, r = [], map = {}) {
 arr.map(item => {
   item.children = [];
   map[item[keyPath]] = item
 })
 arr.map(x => map[x[pid]] ? map[x[pid]].children.push(x) : r.push(x))
 return r
},
//demo 因为这里键是id 所以 我选择传入id 默认是key
let temp = [
 {
   id:'1000',
   name:'哈哈'
 },
 {
   id:'1001',
   name:'呵呵',
   pid:'1000'
 },
 {
   id:'1002',
   name:'嘻嘻',
   pid:'1001'
 },
 {
   id:'1003',
   name:'哈哈哈呢'
 },
]
console.log(this.arrayToTree(temp,'id'))

十四、Tree转数组

  //tree转数组
    function toArray(tree) {
        let nTree = JSON.parse(JSON.stringify(tree)); //深拷贝
        if (!Array.isArray(nTree) || !nTree.length) throw new Error("请传入数组")
        for (let i = 0; i < nTree.length; i++) {
            if (nTree[i].children) {
                // 每次children有值,就把值合并到原始数据tree上去
                //增加tree长度,for循环的长度也会增加 依次处理...
                nTree = nTree.concat(nTree[i].children)
                delete nTree[i].children
            }
        }
        return nTree
    }
    let newArr = toArray(r);

十五、更爽的使用async await

# 我们在实际开发中经常会遇到后端返回接口是 res.data 这种形式,可我们只希望得到data
# 普通写法
this.getDicts('ispgb_clue_state').then(res=>{
    this.xxx = res.data;
})
# 一般写法
let {data} = await this.getDicts('ispgb_clue_state')
this.xxx = data;
# 但是像上面这样写解构的话,如果接口返回错误,就会导致代码出错.
# 更好的写法
this.xxx = (await this.getDicts('ispgb_clue_state'))?.data || []
# 如果接口返回错误则会直接返回空数组 ?.data也可以.任意的你想要的对象属性
```

十六、判断对象或其原型上是否拥有某个属性

     let obj = {
            a: 1,
        }
        // 原型上拥有这个方法
        console.log(obj.toString(), 'toString')
        //只判断对象自身属性
        console.log(obj.hasOwnProperty('toString'), 'hasOwnProperty');  //false
        function searchObjHasAttr(obj, key) {
            return key in obj
        }
        //也可以找到原型上的方法或属性
        console.log(searchObjHasAttr(obj, 'toString'), 'key in obj ') //true

十七、从URL上获取参数并转换为对象格式

const getParameters = URL => JSON.parse(`{"${decodeURI(URL.split("?")[1]).replace(/"/g, '\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`
)
getParameters("https://www.google.com.hk/search?q=js+md&newwindow=1");
// {q: 'js+md', newwindow: '1'}

十八、遍历对象及其属性获取某个需要的属性

  /* 查找一个对象及其子属性中是否有某个属性值 */
export function findObjectAttribute(obj,key,result=[]){
  for(let k in obj){
    if(k===key){
      if(obj[k]!==null&&obj[k]!==undefined){
        result.push(obj[k])
      }
    }else{
      //判断属性是否是对象
      if(Object.prototype.toString.call(obj[k]) === '[object Object]'){
        findObjectAttribute(obj[k],key,result)
      }
      //如果是数组
      if(Array.isArray(obj[k])){
        obj[k].map(item=>{
          findObjectAttribute(item,key,result)
        })
      }
    }
  }
  return result
}

//使用
let find_supervisionDeptOpinion = findObjectAttribute(processProgress,'supervisionDeptOpinion')
if(params?.supervisionDeptOpinion){
  //返回的结果中只要有一条相等 即 返回
  supervisionDeptOpinion = find_supervisionDeptOpinion.some(x=>{
    return x===params.supervisionDeptOpinion 
  })
}
if(params.specialComments===true || params.specialComments===false){
  //返回结果和查询结果匹配成功则为真
  specialComments =  params.specialComments===findObjectAttribute(processProgress,'opinions')?.length>0;
}

十九、下载文件

export default {
  download(file) {
    let url = file.fileUrl;
    let name = file.documentName;
    fetch(url).then(res => res.blob()).then((blob) => {
      const link = document.createElement('a');
      link.style.display = 'none'
      link.href = URL.createObjectURL(blob)
      link.download = name
      document.body.appendChild(link)
      link.click()
      document.body.removeChild(link)
    })
  }
}

二十、数组对象去重+分组

//去重 + 分组 默认根据label去重
filterAndGroup(array, fun,deep='label') {
  let obj = {}
  let groups = {};
  let newArr = array.reduce((prev, cur) => {
    !obj[cur.deep] ? obj[cur.deep] = prev.push(cur) : '';
    return prev
  }, []);
  newArr.forEach(v => {
    let group = JSON.stringify(fun(v));
    groups[group] = groups[group] || [];
    groups[group].push(v);
  });
  return Object.keys(groups).map(group => {
    return groups[group];
  });
},