是否可以在纯 JavaScript 中手动抛出 DOMException 错误? 我读过的文档表明它应该相对容易构建(至少在Java中)
但是,在 Chrome 中,以下代码会返回
TypeError: Illegal constructor
:
// DOM SYNTAX_ERR (12)
var myDOMException = new DOMException(12,"I'm sorry Dave, I'm afraid I can't do that.");
遗憾的是,这是我在阅读W3 文档后所期望的,它似乎根本没有指定构造函数。 (顺便说一句,虽然我对 IDL 并不是特别“熟悉”,但我会假设它们的变体将支持构造函数的规范。)
令人沮丧的是,DOMException 类诱人地潜伏在全局范围内。我该如何使用它? 我可以使用它吗?
更新
自从我写这篇文章以来,我有了一些发现 - 即:
var myDOMException = DOMException.constructor(12,"Error Message");
var myDOMException2 = DOMException.constructor.call(DOMException,DOMException.SYNTAX_ERR,"Error Message");
看起来成功了!
...没那么快。
$> myDOMException instanceof DOMException
false
$> myDOMException2 instanceof DOMException
false
可能更令人反感:
$> myDOMException.constructor
function Number() {
[native code]
}
一如既往,任何帮助将不胜感激。
更新#2
只是为了澄清我返回 DOMException 对象而不是更通用的错误的原因 - 我正在尝试在纯 JavaScript 中实现WHATWG 的定时文本跟踪规范。在许多情况下,需要正确的解决方案来返回 DOMException 对象,特别是代码为 12 (SYNTAX_ERR) 的情况
DOMException
不是一个函数。它是定义了几个常量的“一个对象”。
typeof DOMException === 'object' // true (not 'function')
可以这样使用:try {
throw DOMException;
} catch(e) {
if (e === DOMException)
console.log("caught DOMException")
}
如果您尝试发出
DOMException
信号但不需要 DOMException
的实际实例,则此方法有效。
丑陋的黑客(基本上有效)如果您绝对需要一个具有
DOMException
SYNTAX_ERR
实例,您可以执行一项操作来创建一个实例,然后
throw
:
function createSyntaxException() {
try {
// will cause a DOMException
document.querySelectorAll("div:foo");
} catch(e) {
return e;
}
}
throw createSyntaxException();
当然,抛出的异常的详细信息与您的具体情况不符,但生成的对象将具有正确的代码并通过 instanceof
检查。
var e = createSyntaxException();
console.log(e instanceof DOMException); // true
console.log(e.code === e.SYNTAX_ERR); // true
您可以通过子类化 DOMException
并为其每个(只读)属性添加 getter/setter 来缓解细节问题。
function DOMExceptionCustom() {
var message;
this.__defineGetter__("message", function(){
return message;
});
this.__defineSetter__("message", function(val){
message = val;
});
}
// subclass DOMException
DOMExceptionCustom.prototype = createSyntaxException();
var err = new DOMExceptionCustom();
err.message = "my custom message";
生成的对象具有所需的属性:console.log(err.code === err.SYNTAX_ERR); // true
console.log(err.message); // "my custom message"
console.log(err instanceof DOMExceptionCustom); // true
console.log(err instanceof DOMException); // true
这是我的破解方法。基于 ECMAScript 5 和 WebIDL 的解决方案。 我已经与致力于 WebIDL 的 W3C/ECMAScript 加入工作组
function CustomDOMException(code, message) {
//throw on missing code
if (typeof code !== "number") {
throw TypeError("Wrong argument");
}
//we need the codes, to get the "name" property.
var consts = {
1: "INDEX_SIZE_ERR",
3: "HIERARCHY_REQUEST_ERR",
4: "WRONG_DOCUMENT_ERR",
5: "INVALID_CHARACTER_ERR",
7: "NO_MODIFICATION_ALLOWED_ERR",
8: "NOT_FOUND_ERR",
9: "NOT_SUPPORTED_ERR",
11: "INVALID_STATE_ERR",
12: "SYNTAX_ERR",
13: "INVALID_MODIFICATION_ERR",
14: "NAMESPACE_ERR",
15: "INVALID_ACCESS_ERR",
17: "TYPE_MISMATCH_ERR",
18: "SECURITY_ERR",
19: "NETWORK_ERR",
20: "ABORT_ERR",
21: "URL_MISMATCH_ERR",
22: "QUOTA_EXCEEDED_ERR",
23: "TIMEOUT_ERR",
24: "INVALID_NODE_TYPE_ERR",
25: "DATA_CLONE_ERR"
}
if ((code in consts) === false) {
throw TypeError("Unknown exception code: " + code);
}
//props for adding properties
var props = {};
//generate an exception object
var newException;
try {
//force an exception to be generated;
document.removeChild({})
} catch (e) {
//use it as the prototype
newException = Object.create(Object.getPrototypeOf(e));
}
//get the name of the exception type
var name = consts[code];
//add the properties
var props = {value: null, writable: true, enumerable: false, Configurable: true};
//name
props.value = name;
Object.defineProperty(newException, "name", props);
props.value = code;
Object.defineProperty(newException, "code", props);
props.value = message;
Object.defineProperty(newException, "message", props);
//Make sure it "stringifies" properly
var finalMessage;
var obj = this;
if (typeof message === "function") {
finalMessage = function() {
return message.call(newException)
}
} else {
finalMessage = function() {
return name + ": DOM Exception " + code;
}
}
props.value = function() {
return finalMessage.call(newException)
}
Object.defineProperty(newException, "toString", props);
return newException;
}
还有一些测试:
// Throws SYNTAX_ERR
console.log(new CustomDOMException(12));
// Custom message
console.log(new CustomDOMException(1, "ERROR!"));
// Custom message
console.log(new CustomDOMException(1, function() {
return "Custom Err:" + this.name + " : " + Date.now()
}));
// Throws TypeError
try {
new CustomDOMException(2)
} catch (e) {
console.log(e);
}
// Throws TypeError
try {
new CustomDOMException()
} catch (e) {
console.log(e);
}
// Throws TypeError
try {
new CustomDOMException("Wee!")
} catch (e) {
console.log(e);
}
//Check the inheritance chain
var ext = new CustomDOMException(17);
var isInstance = ext instanceof DOMException;
console.log("instanceof DOMException: " + isInstance)
虽然这是一个老问题,
error.code
error.code
将自动匹配 error.name
TimeoutError
、AbortError
、TypeError
等
当您想要错误显示
error.code = DOMException.SYNTAX_ERR (12)
document.querySelector('a::b')
创建该错误并找出其错误名称。
那么你就可以拥有
throw new DOMException("I'm sorry Dave, I'm afraid I can't do that.", "SyntaxError")
DOMException
更改为
MyOwnError
。
class MyOwnError extends DOMException{
constructor(msg){
super(msg, 'SyntaxError');
}
}
throw new MyOwnError("I'm sorry Dave, I'm afraid I can't do that.", "SyntaxError")
class MyOwnError extends DOMException {
constructor(msg) {
super(msg, 'SyntaxError');
}
}
const err = new MyOwnError("Oops...")
console.log(err.code === err.SYNTAX_ERR); // true
console.log(err.message); // "my custom message"
console.log(err instanceof MyOwnError); // true
console.log(err instanceof DOMException); // true
throw err