调试前端代码二三事--(一)-调试基础

news2024/9/28 5:28:33

一,在网页上调试代码

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script type="text/javascript">
        function test(){
            console.log(1)
            test1()
            console.log(3)
        }
        function test1(){
            console.log(2)
        }
        console.log(0)
        test()
        console.log(4)
    </script>
</body>
</html>

在浏览器打开之后,打开调试面板,在source面板,找到对应的代码,打断点,刷新页面即可开始调试:
在这里插入图片描述

调试时主要的几个按钮及其作用:
在这里插入图片描述

1,恢复代码执行

当我们打了个断点之后,【恢复代码执行】就会跳过这个断点,继续执行后面的代码,直到遇到下一个断点。
在这里插入图片描述

2,跳过函数,单步执行

在这里插入图片描述
可以看到,连续点击时,两次它都不会进入这个test1函数。也就是说,**这个按钮是单步执行,只会从函数调用中出来,而不会进入函数调用之中。**并且,这个单步执行是指:每一步代码点击这按钮后都会断住,一步一行。

3,进入函数调用

和2中相反,2中不会进入函数调用,而这个按钮是遇到函数调用就会进入,并且也是单步执行。

       function test(){
            console.log(1)
            console.log(2)
        }
        function test1(){
            console.log(3)
            setTimeout(()=>{
                console.log(7)
            },1000)
            console.log(4)
            console.log(5)
        }
        console.log(0)//断点位置打这里
        test()
        test1()
        console.log(6)

比较特殊的是,它的名字是【单步进入函数调用】,遇到test1函数中的异步,如setTimeout的时候,它的下一个断点是console.log(7),也就是遇到异步后,它会把同步代码执行完毕,也就是会将主线程中的代码全部执行完毕,然后断点断在下一次的Event Loop事件循环【也就是异步执行完毕后排在事件队列中】。这里来看就是下一个断点在异步后的第一行。

4,跳出函数调用

这个比较简单,就是将当前断点所在的函数体的剩余代码执行完毕,然后跳出这个函数体。下一个断点就在刚跳出这个函数体的地方。

5,强制单步执行

这个和3中的进入函数调用很像,但是不同的地方在于【进入函数调用】在遇到异步代码的时候,会将主线程中的代码全部执行完毕,然后断点断在下一次的Event Loop事件循环【也就是异步执行完毕后排在事件队列中】。
而强制单步执行,就是按照代码执行德顺序,一步步打断点。

6,让断点失效

顾名思义,这个德作用就是让我们打的断点失效掉,比如说我们打了好几个断点。然后将这个按钮点亮,再刷新,会发现所有德断点不再起作用。

7,在报错处断住

就是开启这个按钮后,代码如果有错误,则在运行过程中,会在报错那一行断住。

        function test(){
            console.log(1)
            console.log(2)
        }
        function test1(){
            console.log(a)
            setTimeout(()=>{
                console.log(7)
            },1000)
            console.log(4)
            console.log(5)
        }
        console.log(0)
        test()
        test1()
        console.log(6)

当我没有定义a时,运行代码,就会在这里断住:在这里插入图片描述

二,在vscode中调试代码

1,创建调试配置

在这里插入图片描述

如上图所示,便可进入代码调试。

2,vscode的调试面板

在这里插入图片描述

3,调试的工具面板

这个内容和浏览器上的调试工具差不多,如下图所示:
在这里插入图片描述

三,sourceMap的原理

实际开发过程中,JavaScript脚本正变得越来越复杂。大部分源码(尤其是各种函数库和框架)都要经过转换,才能投入生产环境。
常见的源码转换,主要是以下三种情况:

1)压缩,减小体积。比如jQuery 1.9的源码,压缩前是252KB,压缩后是32KB。
(2)多个文件合并,减少HTTP请求数。
(3)其他语言编译成JavaScript。最常见的例子就是CoffeeScript。

这三种情况,都使得实际运行的代码不同于开发代码,除错(debug)变得困难重重。于是需要引入sourceMap。
sourceMap通常的原理是这样的:

1,在生成线上文件的同时,生成一个映射规则;
2,根据映射规则,将线上文件映射成源文件。

1,生成.map 文件

第一步一般由开发者通过自己的某些工具(如 gulp/webpack)等生成一个 .map 文件:

{
    "version":3,//sourcemap 的版本,一般为 3
    "file":"bundle.js",//编译后的文件名
    "mappings":";;AAAA;AACA;AACA;AACA,c",//位置信息
    "sources":["webpack://tes-test/./index.js"],//源码文件名,可能有多个源文件
    "sourcesContent":["console.log(\"222\")\r\nvar a=2\r\nlet b=4\r\nconsole.log(b)"],//每个 sources 对应的源码的内容,每个文件就是数组的一项
    "names":[],//转换前的变量名
    "sourceRoot":""//源码根目录
}

然后在线上文件的结尾加上这一行:

//@ sourceMappingURL=/path/to/file.js.map

指明线上代码使用的map文件,这样一来,线上文件就可以通过 /path/to/file.js.map 进行 source map 处理。

2,解析映射规则,并将线上文件通过它映射成源文件

这个操作一般由支持 source map 的浏览器来完成。
当第一步指映射文件后,浏览器运行了线上文件,如果浏览器支持了source map,则会对map文件进行解析,主要就是mapping数组的解析,它主要有三层:

 "mappings": "ABCDA,ZSDFS,SDDAF;EEZAV"//位置信息
第一层是行对应,以分号(;)表示,每个分号对应转换后源码的一行。所以,第一个分号前的内容,就对应源码的第一行,以此类推。
第二层是位置对应,以逗号(,)表示,每个逗号对应转换后源码的一个位置。所以,第一个逗号前的内容,就对应该行源码的第一个位置,以此类推。
第三层是位置转换,以VLQ编码表示,代表该位置对应的转换前的源码位置。

主要是第三层的位置转化,使用的是VLQ编码:值得注意的是,第五位名称索引可省略。源文件索引, 源文件行号, 源文件列号也可同时省略。
这表示映射点的数组长度可能是 1、4 或 5。
源映射所有行列号都是从 0 开始计数的。

[生成文件的列]
[生成文件的列,源文件索引,源文件行号,源文件列号]
[生成文件的列,源文件索引,源文件行号,源文件列号,名称索引]

3,mapping的编码规则

示例:

console.log("222");
let b=4;
console.log(b);

第一步:先写处出基本的mapping数组
这三行代码,其中的mapping需要经过如下计算,对应这个[生成文件的列,源文件索引,源文件行号,源文件列号,名称索引]来说的话,这三行分别是:

[0000],[0010],[0020]

第二步:计算相对值

将映射点中每个数字替换成当前映射点和上一个映射点相应位置的差,就是后一个数组的对应值减去上一个的对应值(少于5位的补0即可),于是mapping数组变成:

[0000],[0010],[0010]

第三步:合并数字
将 mappings 中出现的所有数字写成一行,不同映射点使用,(逗号)隔开,不同的行使用;(分号)隔开。于是变成:

0000;0010;0010

第四步:使用VLQ编码将数字编码成字母

1. 如果数字是负数,则取其相反数。
2. 将数字转为等效的二进制。并在末尾补符号位,如果数字是负数则补 1 否则补 03. 从右往左分割二进制,一次取 5 位,不足的补0。如果最高位所在的段不足5位,则前面补0,低位段的后面补04. 将分好的二进制进行倒序。(有的超过5位,如)
5. 每段二进制前面补 1,最后一段二进制补 0。这样每段二进制就是 6 位,其值范围是 064(0,不含64)6. 根据 Base64 编码表将每段二进制转为字母:

在这里插入图片描述
示例:

170 为例,
1)转为二进制即:10101010
2)170 是正数,右边补 0101010100
3)从右往左分割二进制:10100,  10104)不足5位的补 001010,  10100
5)倒序:10100, 01010
6)除最后一个前面补 0,其它每段前面补 1110100, 001010
7)转为十进制:52, 108)查表得到:0K

于是mapping变成:

AAAA;AACA;AACA

浏览器运行了线上文件,如果浏览器支持了source map,发现链接的bundle.js代码尾部有对应的map文件地址,则会解析这个map文件,找到每行代码对应的源代码。这就实现了源代码和编译后代码的映射。

4,使用webpack生成map文件

新建一个项目

npm init -y
npm install webpack webpack-cli -D

根目录配置webpack的webpack.config.js,主要是source-map:

const path = require("path");
module.exports = {
  entry: "./index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js"
  },
  mode: "none",
  devtool:"source-map"
}

新建index.js文件:

console.log("222");
let b=4;
console.log(b);

然后命令行运行npx webpack,就能生成打包文件dist,注意到这个文件夹有两个文件,一个编译后的代码bundle.js:

/******/ (() => { // webpackBootstrap
var __webpack_exports__ = {};
console.log("222");
let b=4;
console.log(b);
/******/ })()
;
//# sourceMappingURL=bundle.js.map

另一个则是map文件,可以看到其中的mapping就是上文计算出来的:

{
    "version":3,
    "file":"bundle.js",
    "mappings":";;AAAA;AACA;AACA,e",
    "sources":["webpack://tes-test/./index.js"],
    "sourcesContent":["console.log(\"222\");\r\nlet b=4;\r\nconsole.log(b);"],
    "names":[],
    "sourceRoot":""
}

然后再在index.html中引入这个bundle.js:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script src="./dist/bundle.js"></script>
</body>
</html>

打开浏览器,便可以看到映射的源代码:
在这里插入图片描述

四,webpack的source map配置

const path = require("path");
module.exports = {
  entry: "./index.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "bundle.js"
  },
  mode: "none",
  devtool:"source-map"
}

在webpack配置不生成map文件,devtool有以下几种情况:

false:不使用 source-map
eval:mode是 develpment的情况下默认值,不会生成 source-map文件,它会在 eval执行的代码中添加 //# sourceURL=注释,同时调试也能定位到代码位置:

webpack有个sourceMap的配置正则表达式:

"^(inline-|hidden-|eval-)?(nosources-)?(cheap-(module-)?)?source-map$"

当我们根据自己的需要,就可以配置出不同的source-map,根据这个正则表达式,可以分成以下几层:

第一层

没有值:没有值的时候,就是剩下source-map:会生成map文件,并且编译后的文件会指向这个map文件。
inline:不会生成map文件,而是将映射文件以dataUrl 的方式内联在打包后的代码最后。
hidden:生成map文件,但是编译后的代码最后不会指向这个map文件,即不做关联
eval:不会生成map文件,但是每个模块,会用一个eval包裹在编译后的代码中

第二层

nosources:map文件中有sourceContent对应的源码内容,其实根据mapping已经能映射源码了,这里的源码内容就可以不要掉,可以缩减map文件的大小。当配置这个的时候,map文件就没有sourcesContent内容。

第三层

cheap:map文件中,通常会有行和列的信息,而实际上,我们只需要映射到行信息即可,列信息可以省略,所以这里可以加上这个cheap参数,把列信息忽略。

第四层

module:当a模块使用loaderA转译一次,再使用B模块转译一次的时候,如果我们想编译后的代码可以直接映射源码,而不是只是映射到最后一次B转移的代码。那么就可以加上这个参数,不管中间转译了多少次,都直接映射源码。

第五层

source-map:只要不是配置的false或者单独一个eval,它是必须要配置的,就是生成map文件,当然,它受前几个配置的影响。

也就是说配置可以用下图总结:
在这里插入图片描述
按照上文的说法,在实际开发过程中,我们常常使用:cheap-module-source-map来配置。

五,调试vue项目代码

我的项目是直接使用webpack搭建的,没有使用vue-cli,当webpack的devtool配置cheap-module-source-map的时候。

1,在chorme浏览器中调试

在这里插入图片描述

2,在vscode中调试代码

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

房产管理系统中CAD图形管理分析

随着技术的不断进步和升级&#xff0c;以及高校房屋建筑物数量的不断扩充&#xff0c;建立房屋资产管理信息系统进行信息化、数字化、图形化房屋资产管理已经是势在必行。学校有庞大的房屋数据、大量的CAD图纸、复杂的房屋分类&#xff0c;建设房屋管理系统&#xff0c;能够加强…

JavaSE高级篇:运行时数据区

文章整理自深入理解Java虚拟机第一章概述第二章&#xff1a;运行时数据区域一&#xff1a;程序计数器二&#xff1a;Java虚拟机栈三&#xff1a;Java堆四&#xff1a;方法区五&#xff1a;运行时常量池六&#xff1a;直接内存第一章概述 Java程序员把内存控制的权利交给了JVM …

Spring MVC 获取参数

1..获取参数 得到单个参数&#xff1a; 运行结果&#xff1a; 得到俩个参数&#xff1a; 运行结果&#xff1a; 得到多个参数&#xff08;对象&#xff09; 运行结果&#xff1a; 通过表单传递参数&#xff1a; 但是&#xff0c;如果我用json传递就不行了&#xff0c;namenul…

【回答问题】ChatGPT上线了!给我推荐20个比较流行的3D点云分割模型

给我推荐20个比较流行的点云 3D 分割模型 这里是 20 个比较流行的点云 3D 分割模型: PointNet PointNet PointCNN Kd-Net SpiderCNN PointSIFT PointASNL PointGroup PointConv PointWeb PointGNN PointPillars PointSESA PointSNE DensePoint PointSAP PointSGN PointGCN Po…

Java 应用与数据库的关系

1.什么是数据库• 数据库就是用来存储和管理数据的仓库• 数据库存储数据的优先。2.数据库的优点• 可存储大量数据;方便检索;• 保持数据的一致性、完整性﹔安全&#xff0c;可共享;• 通过组合分析,可产生新数据。3.数据库的发展历程• 没有数据库,使用磁盘文件存储数据,层次…

2022年度AI亮点项目大起底,ChatGPT是你心目中的第一吗?

回顾2022年&#xff0c;人工智能取得了巨大进步&#xff0c;我有一种感觉&#xff0c;人工智能正在扭曲我的时间感官。谁能相信Stable Diffusion只有4个月大&#xff0c;而ChatGPT的出现才一个多月&#xff1f;感觉只是眨了眨眼&#xff0c;我们差点错过了一个全新的行业。 在过…

Effective_Objective-C_4协议与分类】

文章目录前言23.通过委托与数据源协议进行对象间的通信协议委托模式数据源模式要点总结24.将类的实现代码分散到便于管理的数个分类之中分类Xcode创建一个分类分类需要注意什么要点25.总是为第三方的分类名称加前缀要点26.切勿在分类里面声明属性关联对象扩展可以添加属性要点2…

用javascript分类刷leetcode20.字符串(图文视频讲解)

1143. 最长公共子序列 (medium) 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。如果不存在 公共子序列 &#xff0c;返回 0 。 一个字符串的 子序列 是指这样一个新的字符串&#xff1a;它是由原字符串在不改变字符的相对顺序的情况下删…

系分 - UML【概念】

个人总结&#xff0c;仅供参考&#xff0c;欢迎加好友一起讨论 文章目录UML - Unified Modeling LanguageUML中有4种事物结构事物行为事物分组事物注释事物UML图的分类结构型图&#xff08;静态图&#xff09;行为型图&#xff08;动态图&#xff09;UML图 - 静态图[结构型]类图…

C#枚举器和迭代器

C#枚举器和迭代器 使用foreach语句时&#xff0c;可以依次取出数组里面的元素&#xff0c;原因就是数组提供了“枚举器&#xff08;Enumerator&#xff09;”&#xff0c;枚举器知道元素的位置并返回请求项。 枚举器IEnumerator 枚举器实现了IEnumerator接口&#xff0c;该接…

Angular页面使用指令和路由守卫进行权限控制

在各种业务系统中&#xff0c;为了保证业务及数据安全&#xff0c;除了要求用户必须登录后才能操作外&#xff0c;还针对不同的角色对不同用户设置了各自的访问权限&#xff0c;包括确定的某个页面的权限和页面中特定元素的权限。本文记录了一种Angular页面常用的权限管理方法。…

C++:std::function模板类

一&#xff1a;function定义 类模板 std::function是一种通用的多态函数包装器&#xff0c;它的实例可以对任何可以调用的目标实体进行存储&#xff0c;复制和调用操作。简单的来说&#xff1a;C中有几种可调用对象&#xff1a;函数&#xff0c;指针&#xff0c;lambda表达式&…

区块链之开发命令行操作模块

文章目录功能介绍go语言中flag用法简介项目命令行具体实现链接&#xff1a; 区块链项目github地址项目目前进度&#xff1a;功能介绍 利用命令行操作区块链相较于图形用户界面来说&#xff0c;编写代码简单&#xff0c;同时也可以实现复杂的功能。命令行模块的功能应该满足&am…

Java学习笔记 --- JDBC(1)

一、JDBC概述 基本介绍 1、JDBC为访问不同的数据库提供了统一的接口&#xff0c;为使用者屏蔽了细节问题 2、Java程序员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统&#xff0c;从而完成对数据库的各种操作 3、JDBC原理图 JDBC带来的好处 JDBC是Java提供一套用于数…

安卓移动端调用自然语言处理nlp模型【示例+源码】

安卓可以使用许多不同的方法来调用NLP模型。其中一种方法是使用现有的自然语言处理库,例如 Apache OpenNLP、 Stanford NLP 和 NLTK。这些库提供了许多常用的 NLP 功能,如分词、词干化、命名实体识别和词性标注。另一种方法是使用 TensorFlow Lite 或其他机器学习框架来加载并…

[ins 2022] 针对已见和未见群体的群体推荐中的贝叶斯归纳学习

Bayesian inductive learning in group recommendations for seen and unseen groupshttps://www.sciencedirect.com/science/article/pii/S0020025522008933摘要群组推荐是指向一组用户&#xff08;即成员&#xff09;推荐物品。在预测相关项目时&#xff0c;模型通常会面临未…

fs 文件系统模块

1、什么是 fs 文件系统模块 fs 模块是 Node.js 官方提供的、用来操作文件的模块。它提供了一系列的方法和属性&#xff0c;用来满足用户对文件的操作需求。 方法名 说明 fs.readFile() 用来读取指定文件中的内容 fs.writeFile() 用来向指定的文件中写入内容 如果要在 J…

webflux整合swagger教程V2版

1. yml文件配置 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId><version>2.1.0.RELEASE</version></dependency><!--数据库开始--&…

python @classmethod

1..什么是classmethod classmethod是用来指定一个类的方法为类方法 长的像下面这个样子 1 2 3 class cc: classmethod def f(cls, arg1, arg2, ...): ... cls通常用作类方法的第一参数 跟self有点类似&#xff08; __init__里面的slef通常用作实例方法的第一参数)。…

vue开发环境配置Visual Studio Code配置和安装教程

方便前端vue开发&#xff0c;使用vs code插件安装详细教程&#xff0c;关于vs code可以网络上相关的教程&#xff0c;插件安装如下图所示&#xff0c;大家常用的插件可再分享&#xff0c;与我联系。 1 安装Vue语法高亮显示插件&#xff1a;vetur 2 安装vue语法提示插件&#xf…