2013-07-08 33 views
6

Tôi đã phát triển một thư viện JS nhỏ và đã sử dụng các ngoại lệ lỗi tùy chỉnh đó.Mở rộng các lỗi/ngoại lệ JavaScript

Vì vậy, tôi quyết định thừa kế chúng từ mẹ đẻ Lỗi đối tượng javascript theo cách này (ORLY?):

var MyError = function(){ 
    Error.prototype.constructor.apply(this, arguments); 
}; 

// Inherit without instantiating Error 
var Surrogate = function(){}; 
Surrogate.prototype = Error.prototype; 
MyError.prototype = new Surrogate(); 

// Add some original methods 
MyError.prototype.uniqueMethod = function(){...} 

Hình như thừa kế thông thường .. Nhưng!

var err = new MyError("hello! this is text!"); 
console.log(err.message); // is giving me empty string! 

Tôi đã đọc bài viết về here này và trên MDN, nhưng tất cả đều nói rằng tôi sử dụng một cái gì đó như thế này:

var MyError = function(msg){ 
    this.message = msg; 
}; 

Nhưng câu hỏi của tôi là - nếu không muốn nói trong constructor của Lỗi, sau đó, nơi thông báo được khởi tạo? Có thể ai đó biết cách hàm tạo lỗi gốc hoạt động không?

Cảm ơn!

P.S. Nếu nó thú vị - tôi đã phát triển thư viện Enum.js.

+1

Làm cho nó đơn giản nhất có thể: 'var obj = new Error(); Error.call (obj, "Xin chào, thế giới!"); ' Điều này cũng không có tác dụng. 'Lỗi' là lạ. – Ryan

+1

@minitech: * "' Lỗi 'là lạ." * +1 –

Trả lời

5

Điều bạn đang làm là tốt. Đó là Error đó là vấn đề.

On line này:

Error.prototype.constructor.apply(this, arguments); 

... bạn đang gọi điện thoại Error (gián tiếp) như là một cuộc gọi chức năng bình thường chứ không phải là một phần của một biểu thức new, và defined behavior for Error when you call it as a non-constructor function là tạo ra một mới, trống Error và trả lại (thay vì điền số this).

Bây giờ, trong trường hợp bình thường, những gì bạn đang làm với mẫu thử nghiệm sẽ làm cho việc kiểm tra tiêu chuẩn cho dù nó được gọi là một nhà xây dựng (if (this instanceof Error)) hoạt động. Thật không may, nó dường như không được làm điều đó, và bất cứ điều gì kiểm tra nó sử dụng để xác định nó được gọi như thế nào dường như không được ngay lập tức tuân theo những gì bạn đang cố gắng để làm. Ngay cả điều này (mà chỉ là một bài kiểm tra, không có nghĩa là một cái gì đó bạn thực sự muốn làm):

MyError.prototype = Error.prototype; // You wouldn't normally do this, it's just a test 

... không giải quyết nó.

This answer to another Stack Overflow question điểm đến một cách giải quyết có thể (về cơ bản, chúng ta hãy Error tạo đối tượng và sau đó trở về mà từ MyError):

function MyError(message) { 
    var e = new Error(message); 
    // ...apply your enhancements to `e` 
    return e; 
} 

Không ngạc nhiên thỏa mãn như bạn phải đặt phần mở rộng của bạn trực tiếp trên đối tượng chứ không phải hơn là sử dụng chuỗi nguyên mẫu, nhưng nếu Error từ chối chơi bóng, các tùy chọn của bạn hơi bị giới hạn ...

+0

Cảm ơn bạn đã trả lời. Vì vậy, có vẻ như tôi cần phải làm smth như: 'MyError = function (msg) {var err = new Error(); this.msg = msg; this.stack = err.stack; ...} – gobwas

+0

@gobwas: Tôi vừa cập nhật câu trả lời với một giải pháp có thể có. Tôi không thích nó, nhưng tôi không chắc bạn có nhiều lựa chọn. * Chỉnh sửa * Hoặc, yeah, bạn có thể làm điều đó theo cách đó. –

+1

cảm ơn rất nhiều, và vâng, không có nhiều cú sốc =)) – gobwas