JavaScript优化技巧

作为开发人员,我们一直在寻找让我们的代码更快更好的方法。但在此之前,编写高性能代码需要做三件事:

  • 了解语言及其工作原理
  • 基于用例进行设计
  • 调试!修复!重复

记住这一点

任何傻瓜都可以编写计算机可以理解的代码,优秀的程序员编写人类可以理解的代码。- 丁·福勒 我们来看看如何使 JavaScript代码运行得更快。

延迟

延迟算法将计算延迟到需要执行时才执行,然后生成结果。

1const someFn = () => { 2 doSomeOperation() 3 return () => { 4 doExpensiveOperation() 5 } 6} 7const t = someArray.filter((x) => checkSomeCondition(x)).map((x) => someFn(x)) 8// 现在,如果有需要在执行 9t.map((x) => t())

最快的代码是未执行的代码,所以尽量延迟执行。

JavaScript 使用原型继承,JS 中所有对象都是Object的实例。

MDN说:

尝试访问对象的属性时,不仅会在对象上搜索该属性,还会在对象的原型,原型的原型等上搜索该属性,直到找到匹配属性名或原型链的末端。

对于每个属性,JavaScript引擎都必须遍历整个对象链,直到找到匹配项。 如果使用不当,这会占用大量资源,并影响应用程序的性能。

所以不要这样:

const name = userResponse.data.user.firstname + userResponse.data.user.lastname

而是这样做:

1const user = userResponse.data.user 2const name = user.firstname + user.lastname

使用临时变量来保存链接的属性,而不是遍历访问整条链。

使用转译器之前要三思

在上述情况下,userResponse可能不是对象,如果是对象,它的属性 user 也可能不是对象。所以,在获取值时要进行检查:

1let name = '' 2if (userResponse) { 3 const data = userResponse.data 4 if (data && data.user) { 5 const user = data.user 6 if (user.firstname) { 7 name += user.firstname 8 } 9 if (user.lastname) { 10 name += user.firstname 11 } 12 } 13}

这太啰嗦了。代码越多,bug 就越明显。我们能把它缩小吗?当然,可以使用 JS 中可选的链接、解构赋值来优化它。

1const user = userResponse?.data?.user 2const { firstname = '', lastname = ''} = user 3const name = firstname + lastname

是不是很灵活地,简短? 不要使用这个要注意,Babel 会按照以下方式进行转换:

1'use strict' 2 3var _userResponse, _userResponse$data 4 5var user = 6 (_userResponse = userResponse) === null || _userResponse === void 0 7 ? void 0 8 : (_userResponse$data = _userResponse.data) === null || 9 _userResponse$data === void 0 10 ? void 0 11 : _userResponse$data.user 12var _user$firstname = user.firstname, 13 firstname = _user$firstname === void 0 ? '' : _user$firstname, 14 _user$lastname = user.lastname, 15 lastname = _user$lastname === void 0 ? '' : _user$lastname 16var name = firstname + lastname

当使用转译时,确保你选择了一个更适合你的用例的。

了解SMI和堆号

数字很​​奇怪,ECMAScript将数字标准化为64位浮点值,也称为双精度浮点或Float64表示形式。

如果 JS 引擎以Float64表示形式存储数字,则将导致巨大的性能低下。 JS 引擎对数字进行抽象,使其行为与Float64完全匹配。 与float64运算相比,JS 引擎执行整数运算的速度要快得多。

有时,我们认为像下面这样写法可读比较好:

1const maxWidth = '1000' 2const minWidth = '100' 3const margin = '10' 4getWidth = () => ({ 5 maxWidth: maxWidth - margin * 2, 6 minWidth: minWidth - margin * 2, 7})

评估局部变量

如果getWidth函数被多次调用,那么每次调用它时都会计算它的值。上面的计算并不是什么大问题,因此我们不会注意到任何性能影响。

但是总的来说,运行时的求值的数量越少,性能就越好。

1// maxWidth - (margin * 2) 2const maxWidth = '980' 3// minWidth - (margin * 2) 4const minWidth = '80' 5const margin = '10' 6getWidth = () => ({ 7 maxWidth, 8 minWidth, 9})

使用 Map 而不是 switch/if-else 条件

如果要检查多个条件时,可以使用Map代替 switch/if-else条件。 在Map中查找元素的性能比对switch和if-else条件快得多。

1switch (day) { 2 case 'monday': 3 return 'workday' 4 case 'tuesday': 5 return 'workday' 6 case 'wednesday': 7 return 'workday' 8 case 'thursday': 9 return 'workday' 10 case 'friday': 11 return 'workday' 12 case 'saturday': 13 return 'funday' 14 case 'sunday': 15 return 'funday' 16} 17 18// or this 19 20if ( 21 day === 'monday' || 22 day === 'tuesday' || 23 day === 'wednesday' || 24 day === 'thursday' || 25 day === 'friday' 26) 27 return 'workday' 28else return 'funday'

上面可以使用 Map 来代替

1const m = new Map([ 2 ['monday','workday'], 3 ['tuesday', 'workday'], 4 ['wednesday', 'workday'], 5 ['thursday', 'workday'], 6 ['friday', 'workday'], 7 ['saturday', 'funday'], 8 ['sunday', 'funday'] 9]; 10 11return m.get(day);

if-else 排序

在 React组件中,这种写法还是很常见的。

1export default function UserList(props) { 2 const { users } = props 3 4 if (users.length) { 5 return <UserList /> 6 } 7 return <EmptyUserList /> 8}

在这里,我们在没有用户时渲染<EmptyUserList />否则渲染<UserList />。 有大部分人认为,我们首先处理所有空的的情况,然后再处理有数据的情况。 对于任何读过它的人来说都更清楚,而且效率更高。 也就是说,以下代码比上一个代码更有效。

1export default function UserList(props) { 2 const { users } = props 3 4 if (!users.length) { 5 return <EmptyUserList /> 6 } 7 8 // some resource intensive operation 9 return <UserList /> 10}

当然 users.length 一直有值的话,就使用第一种情况。

类型是你最好的朋友

JavaScript是解释型和编译型语言。 为了产生更有效的二进制文件,编译器需要类型信息。 但是,作为一种动态类型化的语言会使编译器难以进行。

编译器在编译热代码(多次执行的代码)时进行一些假设并优化代码。 编译器花费一些时间来生成此优化的代码。 当这些假设失败时,编译器必须丢弃优化的代码,并退回到解释的执行方式。 这是耗时且昂贵的。

最后

最近断断续续整理了一些阿里、腾讯、字节等等大厂的面试题,目的是想了解一下大厂招聘的技术热点,不断提升学习。

其中包含HTML、CSS、JavaScript、服务端与网络、Vue、浏览器等等,免费分享给大家,还在持续整理收集整理中,有需要的朋友【点击我】免费获取。

篇幅有限,仅展示部分内容

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )