使用CoffeeScript/JavaScript时,应该使用'throw error'还是'throw new Error(error)'?

9

I have the following coffeescript code:

try
   do something
catch error
   log something
   throw error

我应该使用throw new Error(error)还是throw error

它们之间有什么区别?

1个回答

17

与C#或Java等其他语言相同:

  • throw error 抛出相同的错误对象
  • throw new Error(error) 将其包装到新的错误对象中。后者在Java中使用,例如当您需要将checked Exception转换为未检查的异常时。在JavaScript中,您不需要包装异常,因为这会使堆栈跟踪稍微长一点且不太美观。

编辑: 还有一些安全性问题。这是一个例子:

function noWrap() {
    try {
        var o = {}; o.nonexistingMethod();
    } catch (error) {
        throw error;
    }
}

function wrap() {
    try {
        var o = {}; o.nonexistingMethod();
    } catch (error) {
        throw new Error(error);
    }
}

调用noWrap()会产生以下错误信息:
"TypeError: Object #<Object> has no method 'nonexistingMethod'"
// with error.arguments === ['nonexistingMethod', o]

调用wrap()会产生以下错误消息:

"Error: TypeError: Object #<Object> has no method 'nonexistingMethod'"
//  with error.arguments === undefined

通过使用一个包装的错误对象,我们可以隐藏原始错误的arguments。假设您正在编写以下之一:

  • 某种库
  • 将加载在您不拥有的页面上的脚本(例如,某种喜欢或推文按钮)
  • 在加载了一些第三方脚本的页面上的脚本(社交按钮、广告、跟踪代码等)

在上述所有情况下,为了保持安全性,应该包装您的Error对象。否则,您可能会意外地泄漏对内部对象、函数和变量的引用。

编辑2:关于堆栈跟踪。这两种变体都保留了它们。这里是一个工作示例,我在Chrome中得到以下堆栈跟踪:

// No wrapping:
TypeError: Object #<Object> has no method 'nonexistingMethod'
    at noWrap (http://fiddle.jshell.net/listochkin/tJzCF/show/:22:23)
    at http://fiddle.jshell.net/listochkin/tJzCF/show/:37:5
    at http://fiddle.jshell.net/js/lib/mootools-core-1.4.5-nocompat.js:3901:62
    at http://fiddle.jshell.net/js/lib/mootools-core-1.4.5-nocompat.js:3915:20

// Wrapping:
Error: TypeError: Object #<Object> has no method 'nonexistingMethod'
    at wrap (http://fiddle.jshell.net/listochkin/tJzCF/show/:32:15)
    at http://fiddle.jshell.net/listochkin/tJzCF/show/:44:5
    at http://fiddle.jshell.net/js/lib/mootools-core-1.4.5-nocompat.js:3901:62
    at http://fiddle.jshell.net/js/lib/mootools-core-1.4.5-nocompat.js:3915:20 

有人向我建议使用包装版本,它可以提供一个带有完整堆栈跟踪信息的错误对象,否则你只能得到错误信息。 - Mihai Oprea
他声称你会得到堆栈跟踪,因为你使用了console.error(),如果你想把错误对象传递到其他地方,你就会失去它们。我倾向于相信它们会被保留下来,但是调查这个问题会很有趣。 - Mihai Oprea
1
它是依赖于浏览器的。例如,在IE9中,Error对象上没有stack属性。我不知道其他浏览器的情况。 - Andrei Андрей Листочкин

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接