JavaScript调试常见报错以及原因详解
在程序开发中难免会遇到一些错误,在成千上万的代码中去寻找错误很明显相当于大海捞针,为此,每种计算机编程语言都要它独特的一套错误处理与调试机制。当然,JavaScript也不例外。但是,接触过javascript的人都知道,在调试js的过程中有时候真想砸电脑。因为在调试的过程中,控制台给出的错误非常难以理解,其次给出的行号不总有帮助。虽然很多时候都要靠经验去判断,但是控制台给出的错误提示也并不是一点用都没有。因为它会给你提供一些信息帮助你去判断和寻找错误的来源。那这些有用的信息是什么?前面已经说了,每种计算机编程语言都要它独特的一套错误处理与调试机制,每种错误都有对应的错误类型,而当错误发生时,就会抛出相应类型的错误对象。JavaScript同样如此,ECMA-262 定义了下列 7 种错误类型:
Error 错误EvalError 全局错误RangeError 引用错误ReferenceError 参数错误SyntaxError 语法错误TypeError 类型错误URIError 编码错误
其中, Error 是基类型,其他错误类型都继承自该类型。因此,所有错误类型共享了一组相同的属性(错误对象中的方法全是默认的对象方法) 。 Error 类型的错误很少见,如果有也是浏览器抛出的,这个基类型的主要目的是供开发人员抛出自定义错误。
EvalError 类型的错误会在使用 eval() 函数而发生异常时被抛出。ECMA-262 中对这个错误有如下描述: “如果以非直接调用的方式使用 eval 属性的值(换句话说,没有明确地将其名称作为一个Identifier ,即用作 CallExpression 中的 MemberExpression ) ,或者为 eval 属性赋值。 ”简单地说,如果没有把 eval() 当成函数调用,就会抛出错误,例如:
new eval(); //抛出 EvalError eval = foo; //抛出 EvalError
在实践中,浏览器不一定会在应该抛出错误时就抛出 EvalError 。例如,Firefox 4+和 IE8 对第一种情况会抛出 TypeError ,而第二种情况会成功执行,不发生错误。有鉴于此,加上在实际开发中极少会这样使用 eval() ,所以遇到这种错误类型的可能性极小。其他类型错误在接下来会详细说明。
错误类型:
TypeError(类型错误)对象用来表示值的类型非预期类型时发生的错误
错误原因:
当传入函数的操作数或参数的类型并非操作符或函数所预期的类型时,将抛出一个 TypeError 类型错误。
(一)
错误信息:
TypeError: undefined is not a function (Firefox) Uncaught TypeError: undefined is not a function (Chrome)
错误分析:
Uncaught TypeError: 这部分信息通常不是很有用。Uncaught 表示错误没有被 catch 语句捕获,TypeError 是错误的名字。
undefined is not a function: 这部分信息,你必须逐字阅读。比如这里表示代码尝试使用 undefined ,把它当做一个函数。
错误实例:
/* * 当尝试调用一个像方法的值时,这个值并不是一个方法 */ var foo = undefined; foo(); //Uncaught TypeError: foo is not a function /* * 当尝试调用一个对象的方法时,输错了名字,也会触发这个错误提示 */ var x = document.getElementByID('foo'); //Uncaught TypeError: document.getElementByID is not a function
(二)
错误信息:
TypeError: foo is not a function (Firefox) Uncaught TypeError: Cannot read property 'foo' of null (Chrome)
错误分析:
Uncaught TypeError: 这部分信息通常不是很有用。Uncaught 表示错误没有被 catch 语句捕获,TypeError 是错误的名字。
undefined is not a function: 这部分信息,你必须逐字阅读。比如这里表示代码尝试使用 undefined ,把它当做一个函数。
错误实例:
/* * 尝试读取 null 或者 undefined ,把它当成了对象 */ var someVal = null; console.log(someVal.foo);
错误类型:
ReferenceError(引用错误) 对象表明一个不存在的变量被引用。
错误原因:
当你尝试引用一个未被定义的变量时,将会抛出一个ReferenceError引用错误 。
错误信息:
ReferenceError: invalid assignment left-hand side (Firefox) Uncaught ReferenceError: Invalid left-hand side in assignment (Chrome)
错误实例:
/* * 尝试给不能赋值的东西赋值,引起错误 * “left-hand side in assignment” 提及了等号左手边的部分,因为左手边包含不能赋值的东西 */ function doSomething(){}; if(doSomething() = 'somevalue'){}; /* * 当尝试调用一个对象的方法时,输错了名字,也会触发这个错误提示 */ var x = document.getElementByID('foo'); //Uncaught TypeError: document.getElementByID is not a function
错误类型:
RangeError
错误信息:
RangeError: invalid array length (Firefox) RangeError: Invalid array length (Chrome) RangeError: Invalid array buffer length (Chrome)
错误原因:
试图传递一个number参数给一个范围内不包含该number的函数时则会引发RangeError。当传递一个不合法的length值作为Array 构造器的参数创建数组,或者传递错误值到数值计算方法(Number.toExponential(),Number.toFixed() ,Number.toPrecision()),会出现RangeError。
错误实例:
/* * Array 和 ArrayBuffer 的 length(长度) 属性被定义为一个32位无符号整形(unsigned 32-bit integer)的值,所以它只能存储 0 -232-1 之间的数。 * 当创建一个长度为负数或者长度大于等于232 的Array 或者ArrayBuffer 时,或者当设置Array.length 属性为负数或者长度大于等于232 的时候就会触发这个错误 */ new Array(Math.pow(2, 40)) new Array(-1) new ArrayBuffer(Math.pow(2, 32)) new ArrayBuffer(-1) let a = []; a.length = a.length - 1; // 将 length 属性的值设置为 -1 let b = new Array(Math.pow(2, 32) - 1); b.length = b.length + 1; // 将 length 属性的值设置为 2^32
错误类型:
SyntaxError
错误原因:
SyntaxError对象代表尝试解析语法上不合法的代码的错误。当Javascript语言解析代码时,Javascript引擎发现了不符合语法规范的tokens或token顺序时抛出SyntaxError。可能是丢失运算符或者转义字符等。
错误实例
/* * 因为没有使用 ”+“操作符来连接字符串,JavaScript 认为 log 函数的参数的值只是 “PI: ”,在这种情况下,它应该用一个右括号作为结束。 */ console.log("PI: " Math.PI); //Uncaught SyntaxError: missing ) after argument list /* * 一个字符串字面量少了结尾的引号 */ var a='sd; //Uncaught SyntaxError: Invalid or unexpected token
如何解决:
[ ] { } ( ) 这几个符号不配对常常导致出错。检查所有的圆括号和方括号是否配对。行号指出的不仅是问题字符。
Unexpected / 跟正则表达式有关。此时行号通常是正确的。
Unexpected ; 对象或者数组字面量里面有个;通常引起这个错误,或者函数调用的参数列表里有个分号。此时的行号通常也是正确的。