JavaScript 调试
没有调试工具是很难去编写 JavaScript 程序的;你的代码可能包含语法错误,逻辑错误,如果没有调试工具,这些错误比较难于发现;通常,如果 JavaScript 出现错误,是不会有提示信息,这样你就无法找到代码错误的位置
JavaScript 调试工具
在程序代码中寻找错误叫做代码调试。调试很难,但幸运的是,很多浏览器都内置了调试工具;内置的调试工具可以开始或关闭,严重的错误信息会发送给用户
浏览器启用调试工具一般是按下 F12 键,然后通过console调试
console方法
Console 是用于显示 JS和 DOM 对象信息的单独窗口。并且向 JS 中注入1个 console 对象,使用该对象 可以输出信息到 Console 窗口中
有了调试工具,我们就可以设置断点 (代码停止执行的位置), 且可以在代码执行时检测变量
console对象的方法,都可以使用printf风格的占位符。不过,占位符的种类比较少,只支持字符(%s)、整数(%d或%i)、浮点数(%f)和对象(%o)四种
console.log("%d年%d月%d日",2011,3,26);
console.log("圆周率是%f",3.1415926);
%o占位符,可以用来查看一个对象内部情况
还有一种特殊的标示符%c,对输出的文字可以附加特殊的样式,当进行大型项目开发的时候,代码中可能有很多其他开发者添加的控制台语句
var dog = {};
dog.name = "大毛";
dog.color = "黄色";
console.log("%o", dog);
console.log(object[, object, ...])
使用频率最高的一条语句:向控制台输出一条消息。支持 C 语言 printf 式的格式化输出。当然,也可以不使用格式化输出来达到同样的目的:
var animal='frog', count=10;
console.log("The %s jumped over %d tall buildings", animal, count);
console.log("The", animal, "jumped over", count, "tall buildings");
console.debug(object[, object, ...])
向控制台输出一条信息,它包括一个指向该行代码位置的超链接。
console.info(object[, object, ...])
向控制台输出一条信息,该信息包含一个表示“信息”的图标,和指向该行代码位置的超链接。
console.debug(object[, object, ...])
在控制台输出一条消息,包含一个指向代码调用位置的超链接。假如是直接在控制台输入该命令,就不会出现超链接(和console.log()一样)
console.warn(object[, object, ...])
在控制台输出一条带有“警告”图标的消息和一个指向代码调用位置的超链接
console.error(object[, object, ...])
在控制台输出一条带有“错误”图标的消息和一个指向代码调用位置的超链接。error 实际上和 throw new Error() 产生的效果相同,使用该语句时会向浏览器抛出一个 js 异常。
console.assert(expression[, object, ...])
接收至少两个参数,第一个参数的值或返回值为false的时候,将会在控制台上输出后续参数的值
console.assert(1 == 1, object); // 无输出,返回 undefined
console.assert(1 == 2, object); // 输出 object
var isDebug = false;
console.assert(isDebug,'为false时输出的log信息...');
console.dir(object)
输出一个对象的全部属性(输出结果类似于 DOM 面板中的样式)。直接将该DOM结点以DOM树的结构进行输出,可以详细查对象的方法发展等等
var myObject = {
a:'1',
b:2,
c:true,
myFunc:function(){
alert('hello world');
}
};
console.dir(myObject);
console.dirxml(node)
用来显示网页的某个节点(node)所包含的html/xml代码,输出一个 HTML 或者 XML 元素的结构树,点击结构树上面的节点进入到 HTML 面板
<table id="mytable">
<tr>
<td>A</td>
<td>A</td>
<td>A</td>
</tr>
<tr>
<td>bbb</td>
<td>aaa</td>
<td>ccc</td>
</tr>
</table>
<script type="text/javascript">
window.onload = function () {
var mytable = document.getElementById(‘mytable‘);
console.dirxml(mytable);
}
</script>
console.trace()
console.trace()用来追踪函数的调用过程。在大型项目尤其是框架开发中,函数的调用轨迹可以十分复杂,console.trace()方法可以将函数的被调用过程清楚地输出到控制台上
function tracer(a) {
console.trace();
return a;
}
function foo(a) {
return bar(a);
}
function bar(a) {
return tracer(a);
}
var a = foo('tracer');
console.group(object[, object, ...])
这是个有趣的方法,它能够让控制台输出的语句产生不同的层级嵌套关系,每一个console.group()会增加一层嵌套,相反要减少一层嵌套可以使用console.groupEnd()方法
console.log('这是第一层');
console.group();
console.log('这是第二层');
console.log('依然第二层');
console.group();
console.log('第三层了');
console.groupEnd();
console.log('回到第二层');
console.groupEnd();
console.log('回到第一层');
和console.group()相似的方法是console.groupCollapsed()作用相同,不同点是嵌套的输出内容是折叠状态,在有大段内容输出的时候使用这个方法可以使输出版面不至于太长
console.groupEnd()
关闭最近一个由console.group打开的块
console.group('aaa');
console.warn('aaa.aaa');
console.groupEnd();
console.group('bbb');
console.info('bbb.bbb');
console.groupEnd();
console.groupCollapsed()
同 console.group(); 区别在于嵌套块默认是收起的。
console.time(name)
创建一个名字为name的计时器,当调用 console.timeEnd(name);并传递相同的 name 为参数时,计时停止,并输出执行两条语句之间代码所消耗的时间(毫秒)。
console.timeEnd(name)
停止同名的计时器并输出所耗时间(毫秒)
//第一种方法是用console.time来统计实例化1000000个对象所需时间
console.time('Array initialize');
var array = new Array(1000000);
for(var i = array.length-1;i>=0;i--){
array[i] = new Object();
};
console.timeEnd('Array initialize');
//第二种方法使用传统的时间差相减来统计实例化1000000个对象所需的时间
var start = new Date().getTime();
var array1 = new Array(1000000);
for(var i = array.length-1;i>=0;i--){
array[i] = new Object();
};
console.log(new Date().getTime()-start);
console.profile([title])
这是个挺高大上的东西,可用于性能分析。在 JS 开发中,我们常常要评估段代码或是某个函数的性能。在函数中手动打印时间固然可以,但显得不够灵活而且有误差。借助控制台以及console.profile()方法我们可以很方便地监控运行性能;与 profileEnd() 结合使用,用来做性能测试,与 console 面板上 profile 按钮的功能完全相同。
页面加载过程的性能优化是前端开发的一个重要部分,使用控制台的 profiles 面板可以监控所有 JS 的运行情况使用方法就像录像机一样,控制台会把运行过程录制下来
console.profileEnd()
关闭Javascript性能测试开关并输出报告
console.profile('Array initialize');
var array = new Array(1000000);
for(var i = array.length-1;i>=0;i--){
array[i] = new Object();
};
console.profileEnd('Array initialize');
在Profiles面板里面查看就可以看到cpu相关使用信息
console.count([title])
当你想统计代码被执行的次数时,输出该行代码被执行的次数,参数 title 将在输出时作为输出结果的前缀使用。
function myFunction(){
console.count('myFunction被执行的次数:');
}
myFunction();
myFunction();
myFunction();
console.table()
可将传入的对象,或数组以表格形式输出,相比传统树形输出,这种输出方案更适合内部元素排列整齐的对象或数组,不然可能会出现很多的 undefined
var obj = {
foo: {
name: 'foo',
age: '33'
},
bar: {
name: 'bar',
age: '45'
}
};
var arr = [
['foo', '33'],
['bar', '45']
];
console.table(obj);
console.table(arr);
console.timeLine和console.timeLineEnd配合一起记录一段时间轴
console.clear()
清空控制台
控制台的一些快捷键
方向键盘的上下键
大家一用就知晓。比如用上键就相当于使用上次在控制台的输入符号
$
命令返回最近一次表达式执行的结果,功能跟按向上的方向键再回车是一样的
在页面右击选择审查元素,然后在弹出来的DOM结点树上面随便点选,这些被点过的节点会被记录下来,而$0会返回最近一次点选的DOM结点,以此类推,$1返回的是上上次点选的DOM节点,最多保存了5个,如果不够5个,则返回undefined
Chrome 控制台中原生支持类jQuery的选择器
也就是说你可以用$加上熟悉的css选择器来选择DOM节点
copy
通过此命令可以将在控制台获取到的内容复制到剪贴板
keys和values
前者返回传入对象所有属性名组成的数据,后者返回所有属性值组成的数组
var myObj = {name:'angela',sex:'female',hobby:'programs'};
keys(myObj);
values(myObj);
monitor & unmonitor
monitor & unmonitor
monitor(function),它接收一个函数名作为参数,比如function a,每次a被执行了,都会在控制台输出一条信息,里面包含了函数的名称a及执行时所传入的参数。而unmonitor(function)便是用来停止这一监听
function sayHello(name){
alert('hello,'+name);
}
monitor(sayHello);
sayHello('angular');
unmonitor(sayHello);
sayHello('haha');
也就是说在monitor和unmonitor中间的代码,执行的时候会在控制台输出一条信息,里面包含了函数的名称a及执行时所传入的参数。当解除监视(也就是执行unmonitor时)就不再在控制台输出信息了
命令行
控制台的输出面板右边,是控制台的输入面板(Chrome 调试工具对应为下方),在这里除了可以运行常规的 javascript 代码,还内置了相当数量的命令行可以辅助我们的调试工作,下面是一些常用命令行的简单介绍。
$(id)
返回一个给定 id 的元素。
$$(selector)
返回给定的 css 选择器匹配到的一组元素。
$x(xpath)
返回给定的 XPath 表达式匹配到的一组元素。
$0
在 HTML 面板中选中的元素。
$1
上一次在 HTML 面板中选中的元素。
$n(index)
访问最近 5 个被选中过的元素,index 的范围: 0 – 4。
dir(object)
同 console.dir(object)。
dirxml(node)
同 console.dirxml(node)。
clear()
同 console.clear()。
inspect(object[, tabName])()
在合适的(或一个指定的) tab 中检视一个对象。
keys(object)
返回一个对象的所有属性的键。
values(object)
返回一个对象的所有属性的值。
debug(fn)
在函数第一行添加一个断点,使用 undebug(fn) 移除断点。
monitor(fn)
开启一个函数的调用日志,使用 unmonitor(fn) 关闭该功能。非常有用的一个命令,但是它似乎并没有很好地工作。
monitorEvents(object[, types])
开启一个元素的某个事件(或所有事件)被触发时的日志记录。用例如下:
monitorEvents($0,['click'])
上面的命令行被执行后,将开启当前在 HTML 面板中被选中元素的 click 事件监控,一旦这个元素的 click 事件被触发,事件对象将会在控制台输出。如果不指定第二个参数,将对所有事件进行记录。
profile([title])
同 console.profile([title])
设置断点
在这里,我们可以使用快捷键进行操作,常用的快捷键如下:
F9:添加/移除 断点
F10:逐过程,即跳过该语句中的方法、表达式等
F11:逐语句调试,即单步调试,会跳入方法、表达式,进行逐语句的跟踪调试
断点调试是啥
断点调试其实并不是多么复杂的一件事,简单的理解无外呼就是打开浏览器,打开sources找到js文件,在行号上点一下罢了
断点怎么打才合适
假设我们现在正在实现一个加载更多的功能出现了问题,点击以后数据没有加载出来,这时候我们第一时间想到的应该是什么?
我最先想到的是,我点击到底有没有成功?点击事件里的方法有没有运行?好,要想知道这个问题的答案,我们当然是在代码中的点击事件处添加一个断点,然后做什么呢?然后我们当然是回去点击加载更多按钮来确定是否有问题啦
debugger 关键字
这种方法很简单,我们只需要在进行调试的地方加入debugger关键字,然后当浏览器运行到这个关键字的时候,就会提示是否打开调试,我们选择是就可以了。这种调试可以选择调试工具,是新打开vs还是在现有的VS中调试,都可以选择
debugger 关键字用于停止执行 JavaScript,并调用调试函数;这个关键字与在调试工具中设置断点的效果是一样的;如果没有调试可用,debugger 语句将无法工作;下面例子开启 debugger ,代码在第三行前停止执行
var x = 15 * 5;
debugger;
document.getElementbyId("demo").innerHTML = x;
主要浏览器的调试工具
通常,浏览器启用调试工具一般是按下 F12 键,并在调试菜单中选择 "Console"
各浏览器的步骤如下:
Chrome 浏览器
打开浏览器 - 在菜单中选择工具 - 在工具中选择开发者工具 - 最后,选择 Console
Firefox 浏览器
打开浏览器 - 访问页面:http://www.getfirebug.com - 按照说明安装 Firebug
Internet Explorer 浏览器。
打开浏览器 - 在菜单中选择工具 - 在工具中选择开发者工具 - 最后,选择 Console
Opera
打开浏览器 - Opera 的内置调试工具为 Dragonfly,详细说明可访问页面:http://www.opera.com/dragonfly/
Safari
打开浏览器 - 访问页面:http://extentions.apple.com - 按说明操作:install Firebug Lite