我正在尝试用JavaScript创建一个Exception类,虽然我已经使用了很长一段时间的JavaScript,但是我从来没有真正使用过原型设计
是的,所以这是我的代码,
// load the Object Prototype
Exception = Object;
Exception.prototype = new function () {
// set defaults
this.name = "Exception";
this.message = "";
this.level = "Unrecoverable";
this.html = "No HTML provided";
// code so that the console can get the name from this.name insted of using [object Object]
this.getName = function(){
return this.name;
}
// this is the exec of the object prototype the code that is executed when the new Exception call is made
this.exec = function(msg, name, lvl, html){
// create a return variable
var ret;
// check that msg is defined and is not empty
if(typeof(msg) == "undefined" || msg == ""){
throw new Exception("Can't throw exception without a msg");
}
// set up this Exception Object values
this.name = (typeof(name) == "undefined")? this.name : name;
this.level = (typeof(lvl) == "undefined")? this.level : lvl;
this.message = msg;
this.html = (typeof(this.html) == "undefined")? this.html : html;
// delete the getName function so it does not get set though to the console
delete this.getName;
// save the Exception object to our return variable
ret = this;
// re add the getName object to the Exception Object so that it can be called from the console
this.getName = function(){
return this.name;
}
// return the saved Exception object without the getName method
return ret;
}
}
但由于某些原因,在控制台中它返回给出的字符串作为msg
的参数
这是控制台输出i recive
throw new Exception("test");
test
0: "t"
1: "e"
2: "s"
3: "t"
length: 4
__proto__: String
任何帮助将不胜感激
答案 0 :(得分:2)
从您的代码判断我认为这就是您想要做的事情:
Exception.prototype = new Error;
Exception.prototype.constructor = Exception;
function Exception(message, name, level, html) {
if (typeof message !== "string")
throw new Exception("Expected an error message.");
this.message = message;
this.name = name || "Exception";
this.level = level || "Unrecoverable";
this.html = html || "No HTML provided";
}
有关详细信息,请参阅MDN docs。
编辑:如果您遇到原型继承问题,我建议您花一些时间了解它:https://stackoverflow.com/a/8096017/783743
答案 1 :(得分:1)
这是符合您要求的异常“类”的示例:
/*
This is a constructor function. It creates a new Exception object.
Use it with the 'new' keyword , e.g. var e = new Exception("Another error").
*/
function Exception( message, name, level, html ) {
if ( !message ) {
throw 'No exceptions without a message!';
}
/*
These properties may have different values for each instance so set
them here in the constructor rather than adding them to the prototype.
*/
this.message = message;
this.name = name || "Exception";
this.level = level || "Unrecoverable";
this.html = html || "No HTML provided";
}
/*
Overwrite the toString method inherited from Object.prototype
by adding a toString method that shows the name and message.
This method is the same for each instance so add it to the
prototype object instead of having to create and add it to
'this' in the constructor every time an instance is created.
*/
Exception.prototype.toString = function () {
return this.name + ': ' + this.message;
}
试一试
try {
throw new Exception("test");
} catch (e) {
console.log( e instanceof Exception); // true
console.log( e instanceof Error); // false
console.log( e );
// Exception {message: "test", name: "Exception", level: "Unrecoverable"...
}
throw new Exception("test"); // Uncaught Exception: test
如上所述,不是向toString
方法添加Exception.prototype
方法,而是确保toString
对象的Exception
方法返回其name
和{{1}的替代方法是从内置的message
对象的原型继承。
Error
如果Exception.prototype = Error.prototype;
构造函数中没有设置name
对象'错误',这也会使默认Exception
- 但在我们的情况下不需要这样做。
这也意味着添加到Exception
的任何属性都会出现。
Error.prototype
或者,我们可以继承var e = new Exception("Another");
Error.prototype.about = 'This is an Error';
console.log( e.about ); // 'This is an Error'
console.log( e instanceof Exception); // true
console.log( e instanceof Error); // true
实例,而不是继承自Error.prototype
实例,就像Aadit M Shah的回答一样。
Error
以创建新的Exception.prototype = new Error();
对象为代价,这避免了因为他们现在没有指向同一个对象,因此Error
的潜在问题可能会影响Exception.prototype
。对Error.prototype
的更改仍会影响Error.prototype
,因为它们是通过Exception.prototype
对象继承的。
似乎满足您需求的最简单方法可能是避免继承Error
对象或Error
,只需将自己的Error.prototype
方法添加到{{1如第一个例子所示。
答案 2 :(得分:0)
不得不编辑这个,因为我之前发布的一些信息不是真的或非常有帮助。
我之前说过,JavaScript没有私有方法或属性;这是不真实的。私有方法可以通过使用闭包来完成: https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Closures 根据文档,它会带来性能损失。
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function() {
changeBy(1);
},
decrement: function() {
changeBy(-1);
},
value: function() {
return privateCounter;
}
}
})();
要将现有对象“子类化”,您必须使用原型,因为JavaScript不是基于类的语言。这是一个在JavaScript中暴露原型缺点的示例。 以下优秀文档未提及或至少给出适当警告的是“子”对象共享“父”对象的惰性复制实例。更准确地说,如果两个Object具有相同的原型(共享相同的父级),则它们共享该父对象属性的相同INSTANCE。 https://developer.mozilla.org/en-US/docs/JavaScript/Guide/Details_of_the_Object_Model 一些示例代码:
function Employee () {
this.name = "";
this.dept = "general";
this.objectVal=[];
}
function Manager () {
this.reports = [];
}
Manager.prototype = new Employee;
var bob=new Manager();
bob.name="bob";
bob.objectVal.push("should not be in jane");
var jane=new Manager();
jane.name="jane";
console.log(jane.name);//correct
console.log(jane.objectVal);//incorrect shows ["should not be in jane"]
简单值将是正确的,但对象值不会。在该文档的后面有一个针对这个问题的解决方案,即:
function Manager () {
Employee.call(this);
this.reports = [];
}
Manager.prototype = new Employee;
Manager中的Employee.call(this)所做的是它使用Manager的这个上下文调用Employee函数。因此,this.name,this.dept这些行成为Manager的直接属性,而不是通过原型设计,而是通过它们在Manager的上下文中初始化。
行Manager.prototype =新员工;可以省略但是(bob instanceof Employee)将评估为false。
因此,在创建自己的类时,可以将所有需要“由子实例唯一继承”的属性放在“父”中,并使用this.something语法。
“父”的方法可以(并根据一些文档应该)用原型语法指定:
//var Employee=function(){....}
Employee.prototype.EmployeeMethod=function(){}
//or
//var Employee=function(){....}
Employee.prototype={EmployeeMethod:function(){},AnotherOne:function(){},....};
如果你想“子类化”错误(将错误作为异常原型)那么问题是你没有写错误,我无法使用Error作为原型并使用它的属性:
var Exception=function(msg){
// both don't work
// Error.call(Exception.prototype,msg);
Error.call(this,msg);
}
Exception.prototype=new Error;
var e=new Exception("my message");
console.log(e.message);//empty string
不确定为什么会这样,调用Error.call(this,msg)会将Error的属性设置为Exceptions属性(将它们复制到Exception),如果它们位于定义为this.someProperty的Error函数体中。调用Error.call(Exception.prototype,msg)不会将属性复制到Exception,但Exception仍然会通过原型链拥有这些属性。
以下链接指向一篇文章,您可以在其中找到优雅的子类化解决方案,尽管我没有完全理解代码(解决方案在第2部分): http://www.lshift.net/blog/2006/07/24/subclassing-in-javascript-part-1
答案 3 :(得分:0)
首先解决OP的“子类化”错误的原因; IE有几个第三方JavaScript控制台。
我尝试过Firebug lite,它会做你需要的。记录内容时,控制台中不再有[object:Object]: