JS优雅的提效技巧(持续补充)

54 阅读5分钟

大家好,我是鹿萌萌, 如果觉得还不错,那就给个一键3连吧💗💗💗

本文所有代码示例均为es6+和一些常用的lodash写法,强烈建议大家使用es6+语法开发,这样会让你的代码更加规范简介,厚积薄发悄悄滴惊呆你的那些卷王同事。

可以查看萌萌为大家总结了一些工作中常用的es6-es12常用语法

1、判断简化/替代短路或||

假如有下面的这样的一个判断:

if(a === undefined || a === 10 || a=== '15' || a === null) {
    //...
}

超过两个||就可以使用数组的includes来简化这个判断逻辑,可避免代码复杂度过高:

if([undefined, 10, 15, null].includes(a)) {
    //...
}

2、检查是否为空对象

使用ES的写法:

Object.keys({}).length === 0 

使用lodash的写法:

_.isEmpty({}); // true

3、使用Map数据结构代替switch或多个if else判断


const status = 1;

function getStatus(status) {
  switch (+status) {
    case 1:
      return 'todo';
    case 2:
      return 'doing';
    case 3:
      return 'done';
    default:
      return '';
  }
}

getStatus(status) // 'todo'

// 使用Map替代,语法更加简洁明了
const statusMap = new Map([
  [1, 'todo'],
  [2, 'doing'],
  [3, 'done'],
]);
const status = statusMap.get(1); // todo

4、类数组转为数组

可以使用以下方法将类数组arguments转化为数组:

1、最早的方法:

Array.prototype.slice.call(arguments);

2、使用扩展运算符来实现:

[...arguments]

3、使用Array.from

Array.from(arguments)

5、初始化数组

如果想要初始化一个指定长度的一维数组,并指定默认值,可以这样:

const array = Array(6).fill(''); 
// ['', '', '', '', '', '']

如果想要初始化一个指定长度的一维数组,并填充值,可以这样:

const array = Array.from(new Array(100).keys());
  // (100) [0, 1, ..., 98, 99]

5、简单数组去重

扩展运算符 + new Set 去重

const arr = [a,'b','c','a',b,'b'];
const newArr = [...new Set(arr)];

Array.from + Set 去重

const arr = ['a','b','c','a','b'];
const newArr = Array.from(new Set(arr));

6、数组求和、求最大值、最小值

const array  = [5,4,7,8,9,2];

数组求和:

array.reduce((a,b) => a+b);

lodash数组求和:

_.sum([4, 2, 8, 6]);
// => 20

数组最大值:

array.reduce((a,b) => a > b ? a : b);

Math.max(...array)

// lodash
_.max([4, 2, 8, 6]);
// => 8

数组最小值:

array.reduce((a,b) => a < b ? a : b); 

Math.min(...array)
// lodash
_.min([4, 2, 8, 6]);
// => 2

7、清空数组

如果想要清空一个数组,可以将数组的length置于0:

let array = ["A", "B", "C", "D", "E", "F"]
array.length = 0 
console.log(array)  // []

8、拼接数组

1、使用扩展运算符:

const start = [1, 2] 
const end = [5, 6, 7] 
const numbers = [9, ...start, ...end, 8] // [9, 1, 2, 5, 6, 7 , 8]

2、使用数组的concat()方法:

const start = [1, 2, 3, 4] 
const end = [5, 6, 7] 
start.concat(end); // [1, 2, 3, 4, 5, 6, 7]

3、推荐使用数组原型方法push.apply

Array.prototype.push.apply(start, end)

性能比较:push() > concat() > […array1,…array2] , 扩展运算符基本会慢10倍以上,不推荐使用。

9、数组深浅拷贝

数组浅拷贝,只能拷贝一层,不适用于对象数组

 const arr = [1, 2, 3];

 const arr1 = arr.slice(0); // [1,2,3]

 const arr2 = arr.concat(); // [1,2,3]

 const arr3 = [...arr]; // [1,2,3]

 const arr4 = Array.from(arr); // [1,2,3]
 
 // lodash
 const objects = [{ 'a': 1 }, { 'b': 2 }];
 
 const shallow = _.clone(objects); //  [{ 'a': 1 }, { 'b': 2 }]
 console.log(shallow[0] === objects[0]);
// => true

数组深拷贝

1、使用JSON.stringify

JSON.stringify 的目的是将数据转成 json 格式,而 json 有自己的规范,并不是 js 专属,它是跨语言的,各种语言都用统一的 json 格式来通信,所以只能支持各种语言常用的数据类型。

const arr = [{age: 1}, {age: 2}, {age: 3}]; 
const newArr = JSON.parse(JSON.stringify(arr));

2、lodash

const objects = [{ 'a': 1 }, { 'b': 2 }];
 
const deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

3、使用递归

/**
* 深拷贝
* @param {Object|Array} target  拷贝对象
* @returns {Object|Array} result 拷贝结果
*/
  function deepCopy(target) {
    if (Array.isArray(target)) { // 处理数组
      return target.map(item => deepCopy(item));
    } 

    if (Object.prototype.toString.call(target) === '[object Object]') { // 处理对象
       // 先将对象转为二维数组,再将二维数组转回对象(这个过程还是浅拷贝)
       // 所以使用map方法将二维数组里的元素进行深拷贝完了再转回对象
       return Object.fromEntries(Object.entries(target).map(([k, v]) => [k, deepCopy(v)]));
    }
    return target; // 深拷贝要处理的就是引用类型内部属性会变化的情况,像正则、Error、函数、Date这种一般不会发生变化的直接返回原数据就可以
  }

10、过滤错误值

const array = [1, 0, undefined, 6, 7, '', false];

array.filter(Boolean);
// [1, 6, 7]

11、判断数据类型

typeof 可以检测基本数据类型,正则、Date、{}、[]、null 等 输出结果为都为 object

 console.log(typeof 123); // number
 console.log(typeof '123'); // string
 console.log(typeof true); // boolean
 console.log(typeof (undefined)); // undefined
 console.log(typeof function () {}); // function
 console.log(typeof (null)); // object
 console.log(typeof /\w/); // object
 console.log(typeof new Date()); // object
 console.log(typeof {}); // object
 console.log(typeof []); // object
 console.log(typeof new Map()); //object
 console.log(typeof new Set()); //object

instanceof 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

 function Person(){}
 let girl = new Person;
 console.log(girl instanceof Person); // girl的原型链上存在Person的constructor.prototype 所以为true
 console.log(girl instanceof Object); // true

lodash常用的检测数据类型

isUndefined

如果 value 是 undefined ,那么返回 true,否则返回 false

_.isUndefined(undefined);  
// => true  
  
_.isUndefined(null);  
// => false

isNull

如果 value 为null,那么返回 true,否则返回 false

_.isNull(null);  
// => true  
  
_.isNull(undefined);  
// => false

isString

如果 value 为一个字符串,那么返回 true,否则返回 false

_.isString('abc');  
// => true  
  
_.isString(1);  
// => false

isNumber

如果 value 为一个数值,那么返回 true,否则返回 false

_.isNumber(3);  
// => true  
  
_.isNumber(Number.MIN_VALUE);  
// => true  
  
_.isNumber(Infinity);  
// => true  
  
_.isNumber('3');  
// => false

isArray

如果value是一个数组返回 true,否则返回 false

_.isArray([1, 2, 3]);  
// => true  
  
_.isArray(document.body.children);  
// => false  
  
_.isArray('abc');  
// => false  
  
_.isArray(_.noop);  
// => false

isBoolean

如果 value 是一个布尔值,那么返回 true,否则返回 false

_.isBoolean(false);  
// => true  
  
_.isBoolean(null);  
// => false

isFunction

如果 value 是一个函数,那么返回 true,否则返回 false

_.isFunction(function(){});  
// => true  
  
_.isFunction('');  
// => false

isNill

如果 value 为null 或 undefined,那么返回 true,否则返回 false

_.isNil(null);  
// => true  
  
_.isNil(undefined);  
// => true  
  
_.isNil(NaN);  
// => false

isFunction

如果 value 是一个函数,那么返回 true,否则返回 false

_.isFunction(function(){});  
// => true  
  
_.isFunction('');  
// => false