前端性能系列es6的尾调函数优化

简介: 随着前端的应用领域的不断发展,写出高质量的JavaScript对于项目的重要性越来越大,尤其在移动端应用,一段不合理的JavaScript代码可能会导致整个项目的奔溃。一个性能问题可能导致大量用户的流失。因此,追求高性能高质量的JavaScript代码是我们前端工程必须要努力的方向之一。

前言


随着前端的应用领域的不断发展,写出高质量的JavaScript对于项目的重要性越来越大,尤其在移动端应用,一段不合理的JavaScript代码可能会导致整个项目的奔溃。一个性能问题可能导致大量用户的流失。因此,追求高性能高质量的JavaScript代码是我们前端工程必须要努力的方向之一。

尾调函数

  • 尾调用:函数式编程中,某个函数最后一步调用另一个函数被称为尾调用。
function f(x){
  return g(x);
}
  • 类似尾调用,确没有尾调用的效果
// 情况一 y是f函数中的变量,此时f函数仍然在执行
function f(x){
  let y = g(x);
  return y;
}
// 情况一 加1是f函数中执行的,此时f函数仍然在执行
function f(x){
  return g(x) + 1;
}
// 情况一 g函数是f函数中执行的,此时仍是g调用完了f才结束
function f(x){
  g(x);
}
  • 优点:显而易见,es6的尾调函数解决了堆栈溢出的问题,提升了代码运行速度。缺点:支持度低,目前只有严格模式下的safari才支持

上图可以看出,chrome和safari的非严格模式都不支持尾调用优化

原理解析

学过数据结构的都知道,栈的数据结构的概念,先进后出是其基本特征之一。在JavaScript中函数的调用方式也是遵循这种规则,而一个函数从调用栈中弹出的判断依据(JavaScript的垃圾回收)是这个函数中的变量是否在内存中使用。

  • 正常的逻辑来a调用b函数,当执行a时a入栈,a中调用b函数b入栈,b函数执行完毕b出栈,a函数执行完毕a出栈,其实在调用b时候a已经没有用了但是由于JavaScript垃圾回收机制不能识别导致a仍在调用栈中,这其实造成了内存浪费,试想如果a和b是一个非常复杂函数运行时会占用大量的内存空间,如果此时a b同时运行便有可能造成内存泄漏。
function a(){
    b()
}
function b(){
    console.log('this is b func')
}
a()
  • 试想我们在函数a函数中调用b函数,如果把b函数放在a的return中那么不就可以达到释放a的效果,a中的变量,内存不再使用。这样a就会从JavaScript内存的调用栈中弹出。即执行a函数,a入栈,a出栈,b入栈,b出栈。
function a(){
    return b()
}
function b(){
    console.log('this is b func')
}
a()
//参数传递
function sum(a,b){
    let sum = a+b
    console.log(sum)
}
function num(){
    let m =1
    let n=2
    return sum(m,n)
}
num()//==>sum(1,2)

使用实例


尾递归:函数调用自身称为递归,如果尾调用自身称为尾递归。

  • 优点:正常的递归很耗内存,因为递归会同时保存成千上百个调用栈,而尾递归调用可以很好的比 main这个问题
// 正常递归调用 计算输入值到100的和
function sumFun(n) {
  if (n === 100) return 1;
  return n+ sumFun(n+1);
}
sumFun(5)
console.log(sum)
//尾递归调用
function sumFun(n, total) {
  if (n === 100) return total;
  return sumFun(n +1, n+total);
}
sumFun(5, 0) 

尾递归优化的实现

  • 由对比可以发现对于递归函数来说,使用尾递归优化可以大大降低浏览器的内存消耗,提高程序的稳定性和运行速度。但是目前的多数浏览器都不支持这一特性,这就需要我们使用相关的方法去实现这一特性,下面就分享几个尾递归优化的实例:
//先看一个正常的递归函数
function sum(x, y) {
  if (y > 0) {
    return sum(x + 1, y - 1);
  } else {
    return x;
  }
}
sum(1, 100000)//这个会造成堆栈溢出
//RangeError: Maximum call stack size exceeded.
  • 优化方式:蹦床函数
//堆栈溢出原因分析:由于递归函数会不停的往内存栈中存入函数
//解决方式:可以将递归执行改为循坏执行。原理非常简单。尾递归之所以需要优化,原因是调用栈太多,造成溢出,那么只要减少调用栈,就不会溢出。怎么做可以减少调用栈呢?就是采用“循环”换掉“递归”。
//蹦床函数接受一个函数f作为参数。只要f执行后返回一个函数,就继续执行。注意,这里是返回一个函数,然后执行该函数,而不是函数里面调用函数,这样就避免了递归执行,从而就消除了调用栈过大的问题。
function trampoline(f) {
  while (f && f instanceof Function) {
    f = f();
  }
  return f;
}
function sum(x, y) {
  if (y > 0) {
    return sum.bind(null, x + 1, y - 1);
  } else {
    return x;
  }
}
trampoline(sum(1, 100000))

总结


尾调函数是es6新特性,他可以提高我们代码的性能。但是目前ES6的尾调用优化只在严格模式下开启,正常模式是无效的。另外仅仅在Safari浏览器中支持这一属性,chrome和firefox都不支持。尽管如此我认为我们应当去掌握这一特性,因为他有助于我们去理解JavaScript内存机制,只有深入理解一门语言的运行原理,我们才能够去掌握他。


相关文章
|
25天前
|
缓存 前端开发 JavaScript
前端性能优化
在前端重构项目中,为提升用户体验和页面响应速度,采用React框架。遇到页面加载慢和白屏问题,主要归因于数据渲染效率低和状态管理复杂。通过路由懒加载减少初次加载时间,使用Redux Toolkit和immer优化状态管理,配合精细化数据缓存策略。此外,借助React.memo和shouldComponentUpdate避免不必要的渲染,并实施预加载和预渲染策略。关键在于性能意识、技术工具选择、状态管理和用户体验优先。前端开发是技术、用户体验和性能的综合艺术,需持续学习和优化。
|
2天前
|
前端开发 持续交付 开发工具
详细介绍Git的基本原理、在前端开发中的应用以及如何使用Git来优化团队协作
【6月更文挑战第14天】Git是前端开发中的必备工具,它通过分布式版本控制管理代码历史,支持分支、合并和冲突解决,促进团队协作。在前端开发中,Git用于代码追踪、版本控制、代码审查和持续集成部署,优化团队协作。制定分支策略、编写清晰提交信息、定期合并清理分支以及使用Git钩子和自动化工具能进一步提升效率。理解并善用Git,能有效提升前端项目的质量和开发效率。
11 3
|
2天前
|
前端开发 JavaScript 编译器
Svelte框架:编译时优化的高性能前端框架
Svelte是一款由Rich Harris于2016年创建的高性能前端框架,以其编译时优化著称。它将复杂UI逻辑转化为高效的JavaScript,减少运行时开销。Svelte的核心理念是将编译时和运行时的复杂性分离,通过模板语法、组件系统、响应式系统和编译器实现高性能。关键优化策略包括声明式更新、模板内联、计算属性缓存、事件处理优化和代码分割。Svelte提供热模块替换、类型检查和丰富的生态系统,如SvelteKit。其响应式系统基于Reactive Statements,自动更新组件。
7 0
|
3天前
|
缓存 自然语言处理 前端开发
JVM系列8-前端编译与优化
JVM系列8-前端编译与优化
6 0
|
4天前
|
前端开发 JavaScript Java
【前端技术】 ES6 介绍及常用语法说明
【前端技术】 ES6 介绍及常用语法说明
11 4
|
5天前
|
缓存 前端开发 JavaScript
前端性能优化技巧
在当今互联网快速发展的时代,前端性能优化成为了开发者们关注的焦点之一。本文将介绍一些实用的前端性能优化技巧,包括减少HTTP请求、压缩代码、图片优化、减少重绘与重排等方面,帮助开发者们提升网站的加载速度和用户体验。
|
7天前
|
前端开发 算法 JavaScript
优化算法在前端性能提升中的应用
随着互联网应用的日益复杂,前端性能优化成为开发者关注的焦点。本文探讨了优化算法在前端性能提升中的重要作用,包括对JavaScript代码的优化、资源加载的算法选择以及页面渲染的优化策略。通过合理应用优化算法,可以有效提升前端应用的性能和用户体验。
|
12天前
|
存储 缓存 前端开发
全面解析:前端超大文件下载的关键技巧与优化策略
全面解析:前端超大文件下载的关键技巧与优化策略
18 1
全面解析:前端超大文件下载的关键技巧与优化策略
|
14天前
|
前端开发 JavaScript 缓存
如何优化前端网页加载速度
网页加载速度是用户体验和SEO排名的重要指标之一。本文将探讨如何通过优化前端代码、资源加载和网络请求等方面来提高网页加载速度,从而提升用户满意度和网站流量。
|
18天前
|
缓存 前端开发 JavaScript
基于JavaScript的前端性能优化技术探讨
基于JavaScript的前端性能优化技术探讨
28 1