工作中遇到了一个神奇的“bug”,类似于一个这样的代码:
for(let i = 0;i < 20; i++) {
plugins[i].doSomething($dom);
}
最终发现,plugins里的doSomething()方法,总是执行不全,故打了个log一探究竟。
for(let i = 0;i < 20; i++) {
console.log(i);
plugins[i].doSomething($dom);
}
最后输出的则为:
0
1
2
...
10
到10就没有了,也没有任何报错,百思不得其解,最终通过频繁log定位到了问题所在。
/**
*plugin[11]
*/
doSomething($dom) {
...
$dom.doSomeOther();
...
}
这里传入的$dom是个string,没有doSomeOther()方法,所以理应会报错。于是我在这里加了个try catch。
/**
*plugin[11]
*/
doSomething($dom) {
...
try {
$dom.doSomeOther();
} catch(e) {
...
}
...
}
最终输出结果便是:
0
1
2
...
10
12
13
...
19
那为什么在这里加try catch之前,出现错误不会报错呢?
通过mentor非常耐心地教我这个沙雕chrome地调试工具、调用栈怎么用,最终发现了真相。
/**
* A.js
*/
FirstDoThis() {
$dom = ...
try {
B.doSomethingLoop($dom);
} catch (e) {
if (someCondition) {
console.log(e);
}
}
}
/**
* B.js
*/
doSomethingLoop() {
for (let i = 0;i < 20; i++) {
console.log(i);
plugins[i].doSomething($dom);
}
}
由于在整个**doSomethingLoop() **调用的外部包了一层try catch,并且由于历史原因,不知道为何在catch(e)里有一个if的逻辑,plugin[11]没有符合这处的逻辑,所以catch到的error没有log出来,并且由于是处于这个try调用栈内部,所以后面的循环就此终止了。
最终修改为:
/**
* B.js
*/
doSomethingLoop() {
for (let i = 0;i < 20; i++) {
console.log(i);
try {
plugins[i].doSomething($dom);
} catch (e) {
console.log(e)
}
}
}
/**
*plugin[11]
*/
doSomething($dom) {
...
$dom.doSomeOther();
...
}
输出结果就能正确catch并log error了。
0
1
2
...
10
TypeError: doSomeOther is not a function
12
13
...
19
经过这次“实践”,对try catch的作用机理、作用域有了更细致的了解,以及chrome超强大的调试功能,了解了后可以改掉我频繁打log的弱智调试习惯了……