前端性能系列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内存机制,只有深入理解一门语言的运行原理,我们才能够去掌握他。


相关文章
|
缓存 前端开发 UED
如何优化前端性能以提高加载速度
前端性能优化对提升网站加载速度至关重要,直接影响用户体验、SEO排名和转化率。本文介绍了优化前端加载速度的关键技巧,包括最小化HTTP请求、使用CDN、优化图片、利用浏览器缓存、压缩文件和实现懒加载。通过这些方法,可以显著减少页面加载时间,提高网站的整体性能和用户满意度。
|
前端开发 JavaScript 索引
前端性能优化:虚拟滚动技术原理与实战
前端性能优化:虚拟滚动技术原理与实战
1609 80
|
缓存 监控 前端开发
前端性能优化:现代框架的关键策略
前端性能优化:现代框架的关键策略
539 74
|
10月前
|
存储 前端开发 安全
实现“永久登录”:针对蜻蜓Q系统的用户体验优化方案(前端uni-app+后端Laravel详解)-优雅草卓伊凡
实现“永久登录”:针对蜻蜓Q系统的用户体验优化方案(前端uni-app+后端Laravel详解)-优雅草卓伊凡
388 5
|
前端开发 JavaScript 开发者
前端 CSS 优化:提升页面美学与性能
前端CSS优化旨在提升页面美学与性能。通过简化选择器(如避免复杂后代选择器、减少通用选择器使用)、合并样式表、合理组织媒体查询,可减少浏览器计算成本和HTTP请求。利用硬件加速和优化动画帧率,确保动画流畅。定期清理冗余代码并使用缩写属性,进一步精简代码。这些策略不仅加快页面加载和渲染速度,还提升了视觉效果,为用户带来更优质的浏览体验。
|
缓存 前端开发 JavaScript
前端性能优化:打造流畅的用户体验
前端性能优化:打造流畅的用户体验
|
人工智能 JavaScript 前端开发
Vue 性能革命:揭秘前端优化的终极技巧;Vue优化技巧,解决Vue项目卡顿问题
Vue在处理少量数据和有限dom的情况下技术已经非常成熟了,但现在随着AI时代的到来,海量数据场景会越来越多,Vue优化技巧也是必备技能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
机器学习/深度学习 前端开发 算法
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
1311 4
|
缓存 监控 前端开发
探索前端性能优化:关键策略与代码实例
本文深入探讨前端性能优化的关键策略,结合实际代码示例,帮助开发者提升网页加载速度和用户体验,涵盖资源压缩、懒加载、缓存机制等技术。
|
搜索推荐 前端开发 定位技术
前端开发人员SEO优化技术方案
不同的搜索引擎提供了服务后台常见功能来优化网站搜索
373 2

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1229
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    553
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    426
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    428
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    539
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    715
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1380
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    308
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1154
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    495