浏览器断点调试js

说了一些 Chrome 开发者工具的技巧,其实并无涉及到开发者工具最核心的功能之一:断点调试。断点可让程序运行到某一行的时候,把程序的整个运行状态进行冻结。你能够清晰地看到到这一行的全部的做用域变量、函数参数、函数调用堆栈。你能够看到数据是怎么在程序当中流动的,你还能够修改、把玩它们。断点调试让你真正了解一个程序的运做流程。前端

听听亚洲舞王,著名 Web 前端工程师尼古拉斯·赵四是怎么说的:
“断点调试是检验一个前端工程师 debug 能力的惟一标准;是从初级前端工程师成为中高级前端工程师的必经之路;是了解源码和程序运行状态的不二法门!”
看看 IBM 高级工程师,著名IT评论家,王博士怎么说:
“面试一个前端工程师的时候,我通常给他一个bug,而后看他怎么打断点的,一我的的能力在调试过程当中一览无遗。”
除了 debug 的时候会用到,断点调试在你了解一个第三方库源码也颇有帮助。精通断点调试的工程师在阅读源码的效率上比打 `console.log` 高效不止一个数量级。因此懂得如何断点调试,你在 debug 能力、从源码中学习新知识的能力(包括知识的量)会甩其余工程师好几条街。
接下来是小白教程,大神绕路。
=============================== 分割线 ==============================
下面是平常打断点直播,跟着我一步步来,看看断点调试如何可让咱们了解一个程序的运行状态、流程。这里的例子是: 如何经过断点调试,了解React.js 的 `setState` 方法到底干了什么事情。
创建一个 React 组件渲染到页面上,App.js 以下:
import React, { Component } from 'react';react

class App extends Component {
constructor () {
super()
this.state = { name: 'World'}
}面试

handleClick () {
this.setState({ name: 'World 2' })
}windows

render() {
return (
<div onClick={this.handleClick.bind(this)}>
Hello {this.state.name}
</div>
)
}
}数组

export default App
程序很简单:点击 div,经过 `setState` 让原来 “Hello World” 显示成 “Hello World 2”。
Chrome 打开页面,F12 或者 option + command + j (Mac 下) 打开 Chrome 开发者工具。点击第三个 tab : Sources。浏览器

 

而后 command + o(windows 应该是 control + o) ,输入 App.js 查找咱们的文件:前端工程师

 

很棒,第一个就是。而后回车,就能够看到文件的内容:闭包

 

很明显,这就是咱们上述的文件 App.js。点击 div 的时候就调用 handleClick 方法。handleClick 方法内部有一个 setState 的操做,咱们在第 10 行的行号上点一下。app

 

而后点击一下页面上的 `Hello World`,函数

 

 

如今整个页面卡住,什么都操做不了。这是由于咱们的 JavaScript 已经彻底在第 10 行暂停了,整个应用程序是冻结的状态。看看代码右边区域:

Watch 是干嘛的?点击 Watch 旁边的➕,而后输入 `this.state` 看看:

Watch 能够帮你监控执行当前断点所在做用域任何表达式的执行结果,输入 `this.state.name + 'ok'` 看看:

下面 Call Stack 表示这个函数的调用堆栈,也就是 setState 是被哪一个上层函数调用的,上层函数又是谁调用的...

 

Scope 是当前断点的做用域以及全部的闭包做用域以及全局做用域,你能够看到全部做用域的变量。

 

右边的功能很少说了。咱们看看怎么继续打断点,鼠标放到代码里的 `setState` 函数上:

 

这里弹出的信息告诉咱们,this.setState 是函数是在 `ReactComponent.js` 这个文件中定义的,并且仍是个匿名函数,它接受两个参数,一个是 partialState,一个是 callback。直接点击 `ReactComponent.js`,就会到 `setState` 函数定义的地方:

 

咱们看到 `setState` 的原型了,能够看到它其实最主要调用 `this.updater.enqueueSetState` 函数。咱们在这一行上点打个断点:

 

而后点击浏览器上部的蓝色箭头:

 

这个箭头指的是继续执行代码,代码继续执行,在咱们新打的断点的地方又停住了:

 

咱们在旁边能够看到咱们传进来的参数:

整个程序的变量犹如裸奔,一览无遗。继续把鼠标放到:

 

跳到 `ReactUpdateQueue.js` 文件:

 

继续跳

 

继续跳

 

你能够发现,到这里你能够了解到:原来 React.js 的组件实例有两种,一种是公共实例 `publicInstance`,一种是内部实例 `internalIntance`,内部实例存放在 ReactInstanceMap 当中,每次 `setState` 的时候,先取到内部实例。回到 ReactUpdateQueue.js ,咱们一怒之下又打了两个断点:

 

执行:

 

发现 React 把咱们的新的 state push 到了一个叫 queue 的数组中。如下省略 N 次断点,到了:

又省略了 N 次断点
...
最后你会了解当点击页面的时候,React.js 执行了一个叫 `dispatchEvent` 的方法,而后会 `batchedUpdates` 里面执行 transaction.perform 一个事务;这个事务会执行一个函数,这个函数最终会调用咱们的 handleClick 方法使其得以执行;setState 的时候会把新的 state 放到一个更新队列里面,而且把 setState 组件放到一个叫 dirtyComponents 的队列里面;
transaction.perform 每次会执行之后都会执行 closeAll,因此当上述的操做执行完之后,会把 transaction 每一个 wrapper 都 close 掉。有一个 wapper 会调用 `runBatchedUpdates`,它会遍历 `dirtyComponents` 而后一个个去执行 `updateComponent`,`updateComponent` 会从 state queue 拿出最新的 state 而后合并,最后更新页面组件。
上面已经省略了不少细节。可是真实调试过程可能只须要 15 分钟不到,你就能够大体理解到 React.js 到底了发生了什么事情。
这些事情你是用 console.log 无法快速了解到,直接看源码可能也会一头雾水。可是断点调试,方便、快捷、简单。你值得拥有。但实际上,这些事情对于受过较为正统的 CS 专业的培训的人来讲,是习觉得常的事情,就像吃饭、呼吸同样天然。然而最可怕的是:不少前端工程师都不知道。

相关文章
相关标签/搜索