1

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

これが私が受け取ったコンソール出力です

throw new Exception("test");
test
    0: "t"
    1: "e"
    2: "s"
    3: "t"
    length: 4
    __proto__: String

どんな助けでも大歓迎です

4

4 に答える 4

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ドキュメントを参照してください。

編集:プロトタイプの継承に問題がある場合は、それについて学ぶのに時間をかけることをお勧めします:https ://stackoverflow.com/a/8096017/783743

于 2013-01-12T16:21:59.537 に答える
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ことを保証する別の方法。toStringExceptionnamemessageError

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

または、Aadit M Shahの回答のようにError.prototype、インスタンスから継承する代わりに、インスタンスから継承することもできます。Error

Exception.prototype = new Error();

新しいオブジェクトを作成することを犠牲にして、Errorこれは、同じオブジェクトを指していないため、に影響をException.prototype与える変更の潜在的な問題を回避しますError.prototype。への変更は、オブジェクトを介して継承されるため、Error.prototype引き続き影響します。Exception.prototypeError

ニーズを満たすと思われる最も簡単なアプローチは、Errorオブジェクトからの継承を回避するかError.prototype、まったく継承せず、最初の例に示すように独自のtoStringメソッドを追加することです。Exception.prototype

于 2013-01-12T17:12:48.840 に答える
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のプロトタイプの欠点を明らかにする例です。次の優れたドキュメントで言及されていないか、少なくとも適切な警告が表示されていないのは、「子」オブジェクトが「親」オブジェクトの遅延コピーされたインスタンスを共有していることです。より正確には、2つのオブジェクトが同じプロトタイプを持っている(同じ親を共有している)場合、それらはその親オブジェクトのプロパティの同じインスタンスを共有します。 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のthisコンテキストを使用してEmployee関数を呼び出します。したがって、行this.name、this.deptは、プロトタイピングではなく、Managerのthisコンテキストで初期化されるという事実を通じて、Managerの直接のプロパティになります。

行Manager.prototype=new Employee; 省略できますが、(bob instanceof Employee)はfalseと評価されます。

したがって、独自のクラスを作成する場合、「子インスタンスによって一意に継承される」必要があり、this.something構文を使用して「親」にオブジェクト値であるすべてのプロパティを配置できます。

「親」のメソッドは、プロトタイプ構文で指定できます(一部のドキュメントによると指定する必要があります)。

//var Employee=function(){....}
Employee.prototype.EmployeeMethod=function(){}
//or
//var Employee=function(){....}
Employee.prototype={EmployeeMethod:function(){},AnotherOne:function(){},....};

エラーを「サブクラス化」したい場合(例外としてエラーをプロトタイプとして持つ)、問題は、エラーを記述しなかったことです。エラーをプロトタイプとして使用して、そのプロパティを使用することができませんでした。

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)を呼び出すと、エラーのプロパティが、this.somePropertyとして定義されたエラー関数本体にある場合に例外プロパティに設定されます(例外にコピーされます)。Error.call(Exception.prototype、msg)を呼び出しても、プロパティはExceptionにコピーされませんが、Exceptionはプロトタイプチェーンを通じてこれらのプロパティを保持します。

次のリンクは、コードを完全には理解していませんが、サブクラス化の洗練されたソリューションを見つけることができる記事へのリンクです(ソリューションはパート2にあります): http ://www.lshift.net/blog/2006/07/24 / subclassing-in-javascript-part-1

于 2013-01-12T16:18:18.427 に答える
0

そもそも「サブクラス化」エラーのOPの理由に対処するため。IE用のサードパーティのJavaScriptコンソールがいくつかあります。

私はFirebugliteを試しましたが、必要なことを実行します。何かをログに記録するときに、コンソールに[object:Object]が表示されなくなります。

https://getfirebug.com/firebuglite

于 2013-01-14T06:52:35.187 に答える