前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript优化技巧

JavaScript优化技巧

作者头像
前端小智@大迁世界
发布2020-12-21 09:56:24
5890
发布2020-12-21 09:56:24
举报
文章被收录于专栏:终身学习者终身学习者

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

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

记住这一点

任何傻瓜都可以编写计算机可以理解的代码,优秀的程序员编写人类可以理解的代码。- 丁·福勒

我们来看看如何使 JavaScript代码运行得更快。

延迟

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

代码语言:javascript
复制
const someFn = () => {
  doSomeOperation()
  return () => {
    doExpensiveOperation()
  }
}

const t = someArray.filter((x) => checkSomeCondition(x)).map((x) => someFn(x))

// 现在,如果有需要在执行
t.map((x) => t())

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

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

MDN说:

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

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

所以不要这样:

代码语言:javascript
复制
const name = userResponse.data.user.firstname + userResponse.data.user.lastname

而是这样做:

代码语言:javascript
复制
const user = userResponse.data.user
const name = user.firstname + user.lastname

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

使用转译器之前要三思

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

代码语言:javascript
复制
let name = ''
if (userResponse) {
  const data = userResponse.data
  if (data && data.user) {
    const user = data.user
    if (user.firstname) {
      name += user.firstname
    }
    if (user.lastname) {
      name += user.firstname
    }
  }
}

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

代码语言:javascript
复制
const user = userResponse?.data?.user
const { firstname = '', lastname = ''} = user
const name = firstname + lastname

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

代码语言:javascript
复制
'use strict'

var _userResponse, _userResponse$data

var user =
  (_userResponse = userResponse) === null || _userResponse === void 0
    ? void 0
    : (_userResponse$data = _userResponse.data) === null ||
      _userResponse$data === void 0
    ? void 0
    : _userResponse$data.user
var _user$firstname = user.firstname,
  firstname = _user$firstname === void 0 ? '' : _user$firstname,
  _user$lastname = user.lastname,
  lastname = _user$lastname === void 0 ? '' : _user$lastname
var name = firstname + lastname

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

了解SMI和堆号

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

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

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

代码语言:javascript
复制
const maxWidth = '1000'
const minWidth = '100'
const margin = '10'
getWidth = () => ({
  maxWidth: maxWidth - margin * 2,
  minWidth: minWidth - margin * 2,
})

评估局部变量

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

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

代码语言:javascript
复制
// maxWidth - (margin * 2)
const maxWidth = '980'
// minWidth - (margin * 2)
const minWidth = '80'
const margin = '10'
getWidth = () => ({
  maxWidth,
  minWidth,
})

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

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

代码语言:javascript
复制
switch (day) {
  case 'monday':
    return 'workday'
  case 'tuesday':
    return 'workday'
  case 'wednesday':
    return 'workday'
  case 'thursday':
    return 'workday'
  case 'friday':
    return 'workday'
  case 'saturday':
    return 'funday'
  case 'sunday':
    return 'funday'
}

// or this

if (
  day === 'monday' ||
  day === 'tuesday' ||
  day === 'wednesday' ||
  day === 'thursday' ||
  day === 'friday'
)
  return 'workday'
else return 'funday'

上面可以使用 Map 来代替

代码语言:javascript
复制
const m = new Map([
    ['monday','workday'],
    ['tuesday', 'workday'],
    ['wednesday', 'workday'],
    ['thursday', 'workday'],
    ['friday', 'workday'],
    ['saturday', 'funday'],
    ['sunday', 'funday']
];

return m.get(day);

if-else 排序

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

代码语言:javascript
复制
export default function UserList(props) {
  const { users } = props

  if (users.length) {
    return <UserList />
  }

  return <EmptyUserList />
}

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

代码语言:javascript
复制
export default function UserList(props) {
  const { users } = props

  if (!users.length) {
    return <EmptyUserList />
  }

  // some resource intensive operation
  return <UserList />
}

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

类型是你最好的朋友

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

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


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://sendilkumarn.com/blog...

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 延迟
  • 使用转译器之前要三思
  • 了解SMI和堆号
  • 评估局部变量
  • 使用 Map 而不是 switch/if-else 条件
  • if-else 排序
  • 类型是你最好的朋友
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档