2012-01-29 25 views
29

Bằng cách nào đó điều này không có cảm giác như là kết quả của 50 năm lập trình phát triển ngôn ngữ:đúng không theo chuỗi Javascript ngoại lệ

throw "My exception message here"; 

cách chính xác để làm trường hợp ngoại lệ trong Javascript là gì, do đó

  • Chúng có thể được xác định (instanceof)

  • Chúng có thể mang tải trọng khác bên cạnh thư mặc định và theo dõi ngăn xếp

  • Họ "lớp" cơ sở ngoại lệ, do đó debug console và như vậy có thể trích xuất thông tin có ý nghĩa về ngoại lệ

  • ngoại lệ lồng nhau có thể xảy ra (chuyển đổi ngoại lệ khác): nếu bạn cần để bắt một ngoại lệ và rethrow mới một stack trace orignal sẽ còn nguyên vẹn và có thể được đọc có ý nghĩa bằng cách gỡ lỗi cụ

  • Họ làm theo thông lệ tốt nhất javascript

+0

JavaScript thực sự không có những thứ này? Bạn có thể tuần tự hóa bất kỳ đối tượng nào thành chuỗi trong JS không? –

+2

@VladislavZorov: Có, Javascript có các tính năng này. –

+0

Làm rõ sự cần thiết cho các ngoại lệ lồng nhau –

Trả lời

25

throw new Error("message");

hoặc nếu bạn muốn cụ thể hơn sử dụng một trong những Error Objects

Điều quan trọng là bạn phải chắc chắn rằng bạn ném lỗi thật vì chúng chứa theo dõi ngăn xếp. Ném một chuỗi là ngu ngốc vì nó không có bất kỳ dữ liệu meta gắn liền với nó.

Bạn cũng có thể lỗi subclass

// for some sensible implementation of extend 
// https://gist.github.com/1441105#file_1pd.js 
var MyError = extend(Object.create(Error.prototype), { 
    ... 
}); 
+0

"cho một số thực hiện hợp lý của mở rộng" những gì? Tôi không hiểu. –

+3

Mẫu đối tượng mở rộng Javascript là một mẫu thiết kế phổ biến được thực hiện bởi nhiều khuôn khổ Javascript, ví dụ: jQuery http://api.jquery.com/jQuery.extend/ –

+0

@Mikko: Vâng, tôi biết, nhưng tôi không hiểu câu đó. Không có cái gì đó còn thiếu? –

9

một cơ sở "ngoại lệ" trong JavaScript là bui lt-in Error đối tượng:

throw new Error("My exception message here"); 

Bạn có thể xác định trường hợp ngoại lệ tùy chỉnh của bạn như:

function CustomError(message) { 
    this.message = message; 
} 

CustomError.prototype = new Error(); 
CustomError.prototype.constructor = CustomError; 

Kiểm tra cho loại ngoại lệ với instanceof. Ngoài ra còn có handy list of built-in exceptions.

+5

Tránh gọi 'Lỗi mới' trong nhiệm vụ' CustomError' của bạn vì nó gọi hàm khởi tạo trên 'CustomError' để lại dữ liệu theo dõi ngăn xếp phía sau. Ủng hộ bằng cách sử dụng mở rộng Prototypical thay thế ('CustomError.prototype = Object.create (Error);') – Raynos

+0

@Raynos Tại sao bạn sử dụng Object.create (Error) thay vì lỗi mới? Bạn có thể làm rõ sự khác biệt giữa hai? – radicalmatt

2

Bạn có thể tạo đối tượng Error bằng cách gọi số Error constructor. Một đối tượng error có thể có tin nhắn và tên. Khi bắt bạn có thể kiểm tra một tên cụ thể hoặc bạn có thể tạo Loại Lỗi tùy chỉnh bằng cách kế thừa nguyên mẫu Error. Điều này cho phép sử dụng instanceof để khác nhau giữa các loại Lỗi khác nhau.

// Create a new object, that prototypally inherits from the Error constructor. 
function MyError(message) { 
    this.message = message || "Default Message"; 
} 
MyError.prototype = new Error(); 
MyError.prototype.constructor = MyError; 

try { 
    throw new MyError(); 
} catch (e) { 
    console.log(e.name);  // "MyError" 
    console.log(e.message); // "Default Message" 
} 

try { 
    throw new MyError("custom message"); 
} catch (e) { 
    console.log(e.name);  // "MyError" 
    console.log(e.message); // "custom message" 
} 

Ví dụ lấy từ: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error

+2

Tránh 'x.prototype = new y();' favor 'x.prototype = Object.create (y.prototype)' – Raynos

+0

@Raynos Trong môi trường trình duyệt 'Object.create' có thể không có sẵn và bạn cần polyfill. Trong môi trường JavaScript> = 1.8.5, tôi đồng ý. – Eliasdx

+1

nó vẫn còn tốt hơn để polyfill Object.create sau đó sử dụng 'new y();' – Raynos

3

Bạn không thể làm điều đó, và đáp ứng các yêu cầu câu hỏi.

Tại sao?

Sự cố xảy ra với ngăn xếp. Đối tượng lỗi gốc (NativeError từ giờ trở đi), khởi tạo ngăn xếp khi hàm tạo của nó được gọi.Để có được ngăn xếp trong MyError (lớp con lỗi của bạn), bạn phải gọi cho NativeConstructor bên trong hàm tạo của MyError. Vì vậy, lớp MyError của bạn trông giống như sau:

function MyError(msg) { 
    Error.call(this, msg); 
} 

Nhưng, điều này không hiệu quả. Bởi vì theo số HTML5 thông số kỹ thuật:

"nếu bạn gọi Lỗi là hàm, hàm trả về một đối tượng Lỗi mới".

Thay vì hàm tạo lỗi là tốt đẹp và khởi tạo lớp lỗi tùy chỉnh của bạn, nó tạo ra một đối tượng lỗi mà bạn không sử dụng. Tôi đã không tìm thấy một cách để gọi constructor NativeError và có nó khởi tạo lớp con MyError.

Không phải tất cả đều bị mất.

Nếu chúng ta thư giãn các yêu cầu câu hỏi ban đầu và quên "instanceof" để kiểm tra lớp ngoại lệ (vì vậy Java anyway), và sử dụng "name" thay vào đó, nó có thể được thực hiện. Chỉ cần khai báo MyError là:

function MyError(msg, customArg) { 
    var e = new Error(msg); 
    e.name = "MyError"; 
    e.custom = customArg; 
    return e; 
} 

Đây là những gì tôi làm. Thay vì bật "instanceof", hãy bật "tên" thay thế.

+0

Không phải tất cả các thư viện đều tôn trọng biến 'name'. Ví dụ [Bluebird] (http://bluebirdjs.com/docs/api/catch.html) yêu cầu một lỗi tùy chỉnh 'nguyên mẫu' để đi xuống từ' Error.prototype'. Trong thực tế tùy thuộc vào sate của một đối tượng có thể chạy bạn vào rắc rối nếu bạn không cẩn thận 100% kể từ khi tên có thể được đột biến trong khi dựa vào một chuỗi nguyên mẫu là ít mong manh và OOP thành ngữ. – Sukima

Các vấn đề liên quan