写这篇文章的缘由是最近感觉在公司的一些需求和功能开发需求上,对一些js处理不是很熟练,缺乏一些技巧。因此整理了一份在实际开发过程中常用的 js 技巧,灵活地运用,能够解决问题的能力,也会对代码的简洁性有较大的提升。
01.数组去重
正常我们实现数组去重都是通过双层变量或者indexOf的方式。
(1)双层for循环去重
1 | function unique(arr) { |
(2)利用indexOf去重
1 | function unique(arr) { |
但其实有一种更简单的方式:利用Array.from与set去重
1 | function unique(arr) { |
02、截断数组
如果你有修改数组长度为某个固定值的需求,那么你可以试试这个
1 | let arr = [0,1,2,3,4,5]; |
03、获取数组中的最后一项
通常获取数组最后一项,我们用的比较多的是:
1 | let arr = [0,1,2,3,4,5]; |
但我们也可以通过slice操作来实现:
1 | let arr = [0,1,2,3,4,5]; |
04、美化你的JSON
日常开发中,会经常使用到 JSON.stringify,但并不清楚他具体有哪些参数,实际上它有三个参数:
- json: 必须,可以是数组或Object
- replacer: 可选值,可以是数组,也可以是方法
- space: 用什么来进行分割
而我们恰恰可以指定第三个参数space的值去美化我们的JSON。
05、数组转化为对象(Array to Object)
数组转化为对象,大多数同学想到的是通过遍历数组,放入空对象的方式:
1 | var obj = {}; |
但是有一种比较简单快速的方法,即利用展开运算符展开数组
1 | var arr = ["1","2","3"]; |
06、合理利用三元表达式
有些场景我们需要针对不同的条件,给变量赋予不同的值,往往通过if—else的方式:
1 | const isGood = true; |
但是为什么不采用三元表达式呢?
1 | const isGood = true; |
这种也是所谓的 Single line (单行)思想,其实就是代码趋向于极简的风格。
07、转换为数字类型(Convert to Number)
常见转换为数字的方式,可能主要通过parseInt() 、Number() 这两种方式:
1 | const age = "30"; |
其实也可以通过 +
操作来实现转换:
1 | const age = "30"; |
08、转换为字符串类型(Convert to String)
常见转换为字符串的方式,可能主要通过toString()、String() 这两种方式:
1 | let a = 123; |
但也可以通过 value + ""
的方式来实现
1 | let a = 123; |
09、性能追踪
如果想要测试一段 js 代码的执行耗时,可以尝试使用 performance
:
1 | let start = performance.now(); |
10、合并对象 (Combining Objects)
合并两个对象使用的最多 API 就是 Object.assign()
了:
1 | const obj1 = {a:1}; |
实际上通过扩展运算符 (spread operator) 会特别简单:
1 | const obj1 = {a:1}; |
11、短路运算(Short-circuit evalutation)
可以通过 && 或 | | 来简化我们的代码,比如:
1 | if (isOnline) { postMessage()}; |
12、数组扁平化(Flattening an array)
数组的扁平化一般会通过递归
或reduce
去实现。
(1) 递归:
1 | var arr = [1,[2,[3,4]]]; |
(2) reduce:
1 | var arr = [1,[2,[3,4]]]; |
但是 ES6 提供了一个新方法 flat(depth)
, 参数 depth ,代表展开嵌套数组的深度,默认值是1
1 | let arr = [1,[2,[3,[4,[5]]]]]; |
13、求幂运算
平时实现指数运算,用的比较多的应该是 Math.pow()
,比如求 2^10:
1 | console.log(Math.pow(2,10)); |
在 ES7 中引入了指数运算符 **
, **
具有与 Math.pow() 一样的运算结果。
1 | console.log(2**10); // 1024 |
14、浮点数转为整数 (Float to Integer)
一般将浮点数转化为整数会用到 Math.floor() , Math.ceil() , Math.round() 。但其实使用位运算符 ~
,>>
,<<
,|
,>>>
也能够实现取整。
1 | console.log(~~5.96); // 5 |
15、Object.create(null)
在 Vue 和 Vuex 的源码中,作者都使用了 Object.create(null) 来初始化一个新对象。为什么不使用更简洁的 {} 呢?我们来看下 Object.create() 的定义:
1 | Object.create(proto,[propertiesObject]); |
- proto: 新创建对象的原型对象;
- propertiesObject: 可选。要添加到新对象上的可枚举的属性(新添加的属性是其自身的属性,而不是其原型链上的属性)。
我们可以对比分别通过 Object.create(null) 和 {} 创建对象的不同:
从上图可以看到,通过 {} 创建的对象继承了 Object 自身的方法,如 hasOwnProperty 、toString 等,在新对象上可以直接使用。
而使用 Object.create(null) 创建的对象,除了自身属性之外,原型链上没有任务属性。也就是说通过Object.create(null) 的方式可以创建一个纯净的对象,我们可以自己定hasOwnProperty、toString 等方法,完全不必担心会将原型链上的同名方法覆盖掉。
16、拷贝数组
日常开发中,数组的拷贝是一个经常会遇到的场景。实现数组的拷贝有很多骚技巧。
(1)Array.slice()
1 | const arr = [1,2,3]; |
(2)展开操作符
1 | const arr = [1,2,3]; |
(3)使用 Array 构造函数和展开操作符
1 | const arr = [1,2,3,4]; |
(4)Array.concat
1 | const arr = [1,2,3,4]; |
17、避免多条件并列
开发中有时会遇到多个条件,执行相同的语句,也就是多个 ||
的情况:
1 | if (status === "a" || status === "b" || status === "c") {doSomething();} |
这种写法语义性、可读性都不太好。可以通过 switch case 或 includes 的方式进行改造。
(1) switch case
1 | switch (case ) { |
(2) includes
1 | const enum = ["a","b","c"]; |
18.Object.freeze()
在 Vue 的文档中介绍数据绑定和响应时,特意标注了对于经过 Object.freeze() 方法的对象无法进行更新响应。Object.freeze() 方法用于冻结对象,禁止对于该对象的属性进行修改。正是由于这种特性,所以在实际项目中,它有很多的使用场景。
像一些纯展示类的页面,可能存在巨大的数组或对象,如果这些数据不会发生改变,那么你就可以使用 Object.freeze() 将它们冻结,这样 Vue 就不会对这些对象做 setter 或 getter 的转换,可以大大提升性能。