Вручную / искусственно бросая DOMException с JavaScript
можно ли вручную вызвать ошибку DOMException в чистом JavaScript? документация, которую я прочитал предполагает, что это должно быть сравнительно легко построить (по крайней мере в 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.");
к сожалению, это то, что я ожидал после прочтения на В3 документов, которые, похоже, вообще не указывают конструктор. (В стороне, хотя я не особенно "au fait" с IDL, я бы предположили, что их вариант будет поддерживать спецификацию конструкторов.)
к сожалению, класс DOMException дразняще скрывается в глобальной области. Как я могу его использовать? Can я его использовать?
обновление
С тех пор, как я написал это, я сделал несколько открытий, а именно:
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
и, возможно, даже больше offputting:
$> myDOMException.constructor
function Number() {
[native code]
}
как всегда, любая помощь будет принята с благодарностью.
обновление #2
просто чтобы уточнить мои причины возврата объекта DOMException в отличие от более общей ошибки - я пытаюсь реализовать Whatwg'S Timed Text Track spec в чистом JavaScript. Существует несколько экземпляров, в которых для возврата объекта DOMException потребуется правильное решение, в частности с кодом 12 (SYNTAX_ERR.)
2 ответов
в Firefox, по крайней мере, 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
и добавление геттеров / сеттеров для каждого из его (только для чтения) свойств.
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. Я обсуждали С W3C / ECMAScript присоединиться к целевой группе, которые работают на WebIDL. Они сказали, что это в основном невозможно сделать, потому что это зависит от поведения внутренней платформы... но вот что может быть достаточно близко.
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)