前端常见的栈溢出报错

什么是栈溢出?

在前端开发中,栈溢出是指JavaScript引擎执行代码时,调用栈(call stack)变得太大,超过了浏览器或JavaScript引擎所分配的栈空间,从而导致栈溢出错误调用栈是一种数据结构,用于存储函数调用的信息,包括每个函数的局部变量参数返回地址

当一个函数被调用时,它的信息被推送到调用栈的顶部,当函数执行完毕时,该信息被弹出。如果在一个递归函数或深度嵌套的函数调用链中,调用栈的深度变得过大,超过了引擎的限制,就会导致栈溢出。

一般产生溢出的原因如下:

(下面将会举例一些常见的错误)

1.递归调用未正确终止

function fn() {
  return fn();
}
fn();

执行上面的代码出现报错:这是告诉开发者调用栈已经超出了最大限制

上面的函数调用,明显就是有问题的,我们需要确保递归调用有正确的终止条件 

比如我们可以增加传参,设定可以终止的条件,比如:

function fn(count) {
      console.log(count);
  if (count <= 0) {
    return '停止';   //等于小于0时停止递归
  }
  return fn(count - 1);  //每次减1
}
fn(10); // 适当的终止条件

2.事件处理函数中的递归调用

我们获取了一个btn实例进行监听点击事件然后触发handleCllick事件,但是点击后进行了无限制触发

document.getElementById('btn').addEventListener('click',
 function handleClick() {
  handleClick(); // 递归调用
});

上面的代码需要确保不会无限制地在事件处理函数中触发相同的事件

document.getElementById('myButton').addEventListener('click', 
function handleClick() {
  // 处理点击事件的逻辑
});

3.深度嵌套的回调函数

报错代码:

function fn(callback) {
  callback(fn); // 可能导致栈溢出
}

fn(function callback1(val) {
  val(function callback2(val2) {
    // 更多的嵌套回调
  });
});

因为函数调用层次太深,函数递归调用时,系统要在栈中不断保存函数调用产生的变量,如果递归调用太深,就会造成栈溢出,这时递归无法返回

为了避免过度嵌套回调函数,可以使用 Promiseasync/await 进行异步控制

function fn() {
  return new Promise(resolve => {
    resolve();
  });
}

fn()
  .then(() => fn())
  .then(() => fn());

4.变量未定义也会栈溢出

变量未定义通常不会导致栈溢出,而是会引发 ReferenceError 错误。栈溢出通常是由于函数调用栈的深度过大导致的。然而,如果在递归中使用未定义的变量,可能会导致递归调用的栈溢出

当未定义x时,x放fn()前面:

function fn(count) {
//未定义x,会报错
 console.log(count);
  return x+fn(count - 1)
}

fn(5);

 报错如下:

 当未定义x时,x放fn()后面:

function fn(count) {
 console.log(count);
  // 忘记定义变量 x
  return fn(count - 1)+ x 
}

fn(5);

 报错如下:

由于变量 x 没有被定义,它的值为 undefined。在递归调用中,这可能导致栈溢出,因为每次递归都会尝试访问 fn(...)+undefined,从而形成无限递归

我们需要确保所有变量在使用之前都被正确地定义,并且如果没有终止条件,需要加上。


function fn(count) {
  if (count === 0) return 0; // 递归出口,不再调用递归函数
 
  // 定义变量 `x`
    let x = 0;
    console.log(count);
    return fn(count - 1) + x;
}

fn(5);

在实际开发中,为了避免使用未定义的变量,可以使用严格模式 ("use strict") 来帮助捕获未定义的变量

上面说到了严格模式:

简单的了解下什么是严格模式,我们可以通过使用严格模式 ("use strict") 来强制执行更严格的语法错误处理规则,其中包括捕获未定义的变量。

严格模式能够帮助我们更早地发现潜在的问题,因为我们可能有些东西在平时使用中被忽略或者遗忘的。

在Vue 2中,可以在单文件组件或者JavaScript文件顶部启用严格模式,加上"use strict"即可,

请注意,这行代码必须位于文件的最顶部,不能有任何代码出现在它的前面。

如下所示:

例如vue文件中:
<script>
"use strict";

export default {
  // 组件定义
}
</script>
//------------------------------------
单独的纯js文件中:

// 在 JavaScript 文件的顶部启用严格模式
"use strict";

// 其他代码...

严格模式下会抛出的错误:

1.未定义变量报错: 在严格模式下,如果使用未声明的变量,会抛出 ReferenceError 错误。

2.删除不可删除的属性报错: 在严格模式下,尝试删除一个不可删除的属性会抛出 TypeError 错误。

3.禁止使用 with 语句: 在严格模式下,使用 with 语句会导致语法错误

WITH方法:

 由于大量使用with语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序时,不建议使用with语句,现在这个with已经废弃了

with 语句扩展一个语句的作用域链,语法为:

with (expression)  //将给定的表达式添加到在评估语句时使用的作用域链上。表达式周围的括号是必需的。
  statement  //任何语句。要执行多个语句,请使用一个块语句 ({ ... }) 对这些语句进行分组。

with'语句将某个对象添加到作用域链的顶部,如果在 statement 中有某个未使用命名空间的变量,跟作用域链中的某个属性同名,则这个变量将指向这个属性值。如果沒有同名的属性,则将拋出ReferenceError异常。

使用举例:

使用了JavaScript变量和Math对象的方法来计算。

var a, x, y;
var r = 10;

with (Math) {
  a = PI * r * r;      //圆的面积
  x = r * cos(PI);     //计算了在极坐标系中半径为 r,角度为 PI 弧度的点的 x 坐标
  y = r * sin(PI / 2); //计算了在极坐标系中半径为 r,角度为 PI / 2 弧度的点的 y 坐标
}

//其中:
with (Math) { ... }: 
这个语句块用于指定之后的代码中的变量或函数来自于 Math 对象。
这样可以省略每次引用 Math 对象的前缀。

解决了像:(简单举例)

获取对象obj的属性的值

原来的:
var a = obj.a;
var b = obj.b;
var c = obj.c;

使用with后:
with(obj){
    var a = a;
    var b = b;
    var c = c;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/366368.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

flutter实现:使用三方组件syncfusion_flutter_datagrid

Syncfusion Flutter DataGrid 是一个用于 Flutter 的数据网格组件&#xff0c;它提供了丰富的功能来显示和编辑数据。这个组件提供了灵活的配置选项&#xff0c;使得开发者能够根据需要定制数据的显示和编辑方式。 项目中有两个需求&#xff0c;一是在列表中要使用可变高度&am…

flask基于大数据的旅游景区推荐可视化大屏系统 juj13-vue

本论文分为六个章节。 第一章&#xff0c;绪论&#xff0c;其包含课题背景及意义&#xff0c;现国内外的发展现状&#xff0c;本课题要研究的内容&#xff0c;所使用开发工具的描述等信息。 第二章&#xff0c;主要介绍了系统的开发技术。 第三章&#xff0c;先讲述功能需求分析…

水闸安全监测系统的主要监测项和优势

一、行业背景 水闸工程作为防洪保安、调控水资源的重要设施,其安全运行至关重要。为规范水闸安全监测、掌握水闸运行性态、评价施工质量、反馈设计指标、降低失事风险等&#xff0c;有必要在水闸主要结构病害特征分析的基础上&#xff0c;确定了水闸监测项目主要包括闸墩及翼墙…

提升 Web 请求效率:Axios request 封装技巧

在开发中&#xff0c;为了提高效率&#xff0c;通常对 Axios 进行封装&#xff0c;简化了请求的发送和对响应的处理。同时&#xff0c;统一错误处理机制有助于维护代码的清晰和一致性。本文介绍了一些高效封装 Axios 请求的方法。 封装理念 通过创建一个请求函数&#xff0c;我…

遇到ubuntu设置交叉编译环境的问题

今天交叉编译器一直没安装成功&#xff0c;环境变量也配置了还是不对&#xff0c;最后发现Ubuntu是64位的要装 然后就好了 另外在进行嵌入式Linux开发的时候&#xff0c;要把主机、虚拟机、以及开发板设置在同一网段下&#xff0c;虚拟机一般设成临时的就可以&#xff0c;但是…

Kubernetes实战(二十一)-event事件持久化

默认情况下&#xff0c; K8S 会将事件保留在 etcd 中一个小时&#xff0c;超过1小时的事件将无法看到&#xff0c;所以 K8S 默认保留事件的时间不足以来更深入的了解集群&#xff0c;所以将事件导出到集群外存储是有必要的&#xff0c;以实现可观测性和告警。 Event事件持久化…

Vue3.0(一):Vue的引入-options api-模板语法

Vue的引入方式 CDN方式进行引入 将以下 script标签引入即可 <script src"https://unpkg.com/vue3/dist/vue.global.js"></script><!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><met…

dolist案例实现

这段代码是一个使用Vue.js实现的简单的ToDoList&#xff08;待办事项列表&#xff09;应用。我们分几个部分详细解释这段代码。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>todolist</title&g…

带大家做一个,易上手的家常孜然猪肉挂面

准备一定猪瘦肉 加一把挂面 猪瘦肉切片 一小把花椒 一定量干辣椒(看你想让它多辣) 四个左右大料 一根大葱 一块生姜 四瓣大蒜 蒜切片 单独装起来备用 大葱切段 生姜切片 和干辣椒 花椒 大料装一起 起锅烧油 下瘦肉 翻炒一下 然后倒入 葱姜 干辣椒 花椒 大料 翻炒均匀 …

Mysql单行函数练习

数据表 链接&#xff1a;https://pan.baidu.com/s/1dPitBSxLznogqsbfwmih2Q 提取码&#xff1a;b0rp --来自百度网盘超级会员V5的分享 单行函数练习 单行函数(一行数据返回一个结果) #1.显示系统时间(注:日期时间) #2.查询员工工号,姓名,工资以及提高百分之20后的结果(new…

何以穿越产业周期?解读蓝思科技2023年增长密码

1月30日晚&#xff0c;蓝思科技发布了2023年业绩预告&#xff0c;2023年预计实现归母净利润29.38亿元-30.60亿元&#xff0c;同比增长20%-25%。 松果财经注意到&#xff0c;蓝思科技通过垂直整合&#xff0c;构筑了更具竞争力的产业链条。一方面&#xff0c;公司打造了包含ODM…

MyBatis框架-多对一处理

多对一的处理 多个学生对应一个老师如果对于学生这边&#xff0c;就是一个多对一的现象&#xff0c;即从学生这边关联一个老师&#xff01; 数据库设计 CREATE TABLE teacher (id INT(10) NOT NULL,name VARCHAR(30) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEINNODB DEFAULT C…

【Redis】Redis集群方案应该怎么做 都有哪些方案

&#x1f34e;个人博客&#xff1a;个人主页 &#x1f3c6;个人专栏&#xff1a;Redis ⛳️ 功不唐捐&#xff0c;玉汝于成 目录 前言 正文 &#xff08;1&#xff09;twemproxy &#xff08;2&#xff09;codis &#xff08;3&#xff09;redis cluster3.0自带的集群 …

Docker进阶篇-DockerFile

一、简介 Dockerfile是用来构建Docker镜像的文本文件&#xff0c;是由一条条构建镜像所需的指令和参数构成的脚 本。 构建步骤&#xff1a; 1、编写Dockerfile文件 2、docker build命令构建镜像 3、docker run依镜像运行容器实例 二、Docker构建过程解析 1、Dockerfile…

MySQL数据库入门(概念+使用)

目录 1. 数据库的概念 1.1 数据库的存储介质 1.2 主流数据库 2. MySQL的基本使用 2.1 链接数据库 2.2 服务器管理 2.3 数据库&#xff0c;服务器和表关系 2.4 简单MySQL语句 3. MySQL架构 4. SQL分类 5. 存储引擎 本篇完。 1. 数据库的概念 数据库是按照数据结构来…

LeetCode 热题 100 | 链表(上)

目录 1 基础知识 1.1 空指针 1.2 结构体 1.3 指针访问 1.4 三目运算符 2 160. 相交链表 3 206. 反转链表 4 234. 回文链表 菜鸟做题第三周&#xff0c;语言是 C 1 基础知识 1.1 空指针 使用 nullptr 来判断是否为空指针&#xff1a; if (headA nullptr) …

手把手教你搭建属于自己的网站(获取被动收入),无需服务器,使用github托管

大家好&#xff0c;我是亚洲著名程序员青松&#xff0c;本次教大家如何搭建一个属于自己的网站。 下面是我自己搭建的一个网站&#xff0c;是一个网址导航网站。托管在了github上面&#xff0c;目前已经运营了三个月&#xff0c;每天的访问量大约有100ip左右。 下图是在51.la上…

Flutter组件 StatefulWidget、StatelessWidget 可继承写法

前言 学过Java的同学&#xff0c;应该都知道面向对象语言的三大特征&#xff0c;封装、继承、多态&#xff1b; Dart也是面向对象的语言&#xff0c;但是在Flutter中的很多组件都被下划线 _ 标记为私有&#xff0c;导致无法继承&#xff0c;本文将介绍一种非私有的创建组件写…

Springboot 自定义参数配置化,密钥,密码,文件保存路径

application.properties 和 application.yml 都是一样的配置方法&#xff0c;只是格式不一样 定义配置文件 server.port8080 image.save.pathE:\ #自定义文件保存路径读取配置文件 Value("${image.save.path}")private String filePath;//E:\优化配置文件 如果我参…

处理安装uni-ui依赖一直安装不上

根据官方的文档去安装&#xff0c;我这边把npm换成了pnpm。 搞了一个小时没搞明白为什么下载不下来依赖&#xff0c;原因是镜像的问题。 处理方式&#xff1a;安装了cnpm&#xff0c;去访问国内镜像 安装cnpm&#xff0c;使用国内镜像 npm install -g cnpm --registryhttps…