2013-07-25 37 views
6

Tôi đang làm việc với API RESTful và mã Javascript của tôi đang thực hiện truy vấn REST thông qua cuộc gọi $ .ajax() của jQuery.Khai báo hằng số nguyên mẫu Javascript

tôi đã thực hiện một lớp Nghỉ ngơi javascript, mà tôi sẽ hiển thị bên dưới (rất đơn giản):

var Rest = function (baseUrlPath, errorMessageHandler) { 
     ... 
    }; 

// Declare HTTP response codes as constants 
Rest.prototype.STATUS_OK = 200; 
Rest.prototype.STATUS_BAD_REQUEST = 400; 

... // other rest methods 

Rest.prototype.post = function (params) { 
     $.ajax({ 
      type: 'POST', 
      url: params.url, 
      data: params.data, 
      dataType: 'json', 
      contentType: 'application/json; charset=utf-8', 
      beforeSend: this._authorize, 
      success: params.success, 
      error: params.error || this._getAjaxErrorHandler(params.errorMessage) 
     }); 
     }; 

... // more rest methods 

Rest.prototype.executeScenario = function (scenarioRef) { 
     var self = this; 

     this.post({ 
      url: 'myurlgoeshere', 
      data: 'mydatagoeshere', 
      success: function (data, textStatus, xhr) { 
       if (xhr.status == 200) { 
        console.log("everything went ok"); 
       } 
      }, 
      error: function (xhr, textStatus, errorMsg) { 
       // TODO: constants 
       if (404 == xhr.status) { 
        self.errorMessageHandler("The scenario does not exist or is not currently queued"); 
       } else if (403 == xhr.status) { 
        self.errorMessageHandler("You are not allowed to execute scenario: " + scenarioRef.displayName); 
       } else if(423 == xhr.status) { 
        self.errorMessageHandler("Scenario: " + scenarioRef.displayName + " is already in the queue"); 
       } 
      } 
     }); 
    }; 

Mã này hoạt động như dự định, tuy nhiên tôi đã quyết định thêm một số hằng số để giúp làm đẹp mã và nâng cao dễ đọc. Tôi có ví dụ một số nơi trong mã của tôi, nơi tôi đang kiểm tra cho xhr.status == 200 hoặc xhr.status == 400 và như vậy.

tôi có thể khai báo các biến lớp học như Rest.prototype.STATUS_OK = 200;

Nhưng biến là có thể chỉnh sửa, và tôi không thể nghĩ ra cách để làm cho họ không thay đổi. Trong mã của tôi ví dụ tôi có thể làm một this.STATUS_OK = 123; và điều này sẽ sửa đổi biến. Tôi đã chơi xung quanh với từ khóa const, không có may mắn.

tôi đã thấy điều này: Where to declare class constants?, nhưng không có nhiều trợ giúp.

Ai đó có thể chỉ cho tôi đúng hướng để làm cách nào để biến những trường này thành một hằng số thay vì một biến không?

+0

Xin lưu ý rằng "trường" là * thuộc tính *, chứ không phải * biến *. Đối với các biến bạn chỉ đơn giản có thể sử dụng ['const' keyword] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) khi được hỗ trợ. Nhưng bạn sẽ địa phương phạm vi nó anyway :-) – Bergi

Trả lời

8

Sử dụng ECMAScript 5 của Object.defineProperty bạn có thể tạo ra một giá trị un-settable:

Object.defineProperty(Rest, "STATUS_OK", { 
    enumerable: false, // optional; if you care about your enumerated keys 
    configurable: false, 
    writable: false, 
    value: 200 
}); 

Hoặc, vì đó là những giá trị mặc định, chỉ cần làm:

Object.defineProperty(Rest, "STATUS_OK", { value: 200 }); 

Điều này làm cho Rest.STATUS_OK yield 200 khi được truy cập, nhưng nó sẽ không phản hồi lại các nỗ lực xác định lại hoặc delete nó. Hơn nữa, configurable: false sẽ ngăn chặn bất kỳ nỗ lực xác định lại thuộc tính bằng lệnh gọi defineProperty tiếp theo.

Tuy nhiên, điều này không hoạt động trong older browsers that don't support ES5's defineProperty (đặc biệt là IE8 trở xuống).

+0

Đó là một giải pháp tốt, nhưng có vẻ như một kludge phải viết một vài dòng mã (tôi biết một câu lệnh của nó, nhưng vẫn còn một số dòng để dễ đọc) để thiết lập một hằng số. Và chắc chắn rất nhiều công việc khi bạn có rất nhiều hằng số để khai báo. Có lẽ sẽ có sự hỗ trợ tốt hơn cho điều này trong tương lai khi IE8 và dưới đây được loại bỏ. – Husman

+5

@Husman: Trên thực tế bạn có thể bỏ qua tất cả các dòng nhưng 'giá trị', vì' false' là giá trị mặc định cho những giá trị đó. – Bergi

+0

@Bergi Cuộc gọi tốt; Tôi đã chỉnh sửa câu trả lời của tôi theo đề xuất của bạn. – apsillers

1

Điều này sẽ không thể thực hiện được trong Javascript. Điều tốt nhất bạn có thể làm, là tạo ra một số đóng cửa như công cụ:

var StatusCode = (function() { 
    var STATUS_OK = 200, 
     STATUS_BAD_REQUEST = 400; 

    return { 
     getOk: function() { 
      return STATUS_OK; 
     }, 
     getBadRequest: function() { 
      return STATUS_BAD_REQUEST; 
     } 
    } 

}); 

Và sử dụng nó như StatusCode.getOk() === 200. Điều này sẽ giúp bạn không thể thay đổi những 'hằng số' này, nhưng sẽ lại có hại cho khả năng đọc của bạn (điều này có lẽ là dựa trên ý kiến). Tôi sẽ chỉ giữ các hằng số đó bằng chữ hoa để đánh dấu chúng là hằng số, mặc dù chúng có thể thay đổi.

+1

+1; Hơn nữa, không có lý do tại sao một người nào đó không thể chỉ đơn giản là ghi đè lên 'getOk' với' function() {return "một cái gì đó khác"; } '. – apsillers

+1

@apsillers điểm tốt. Như một dòng dưới cùng, bạn không thể bảo vệ an toàn bất cứ điều gì trong javascript. Ví dụ điển hình - ngay cả 'không xác định' có thể bị ghi đè. –

1

Bạn có thể xác định trạng thái là getters, nhưng AFAIK này sẽ không hoạt động trong IE8 trở lên.

var Rest = function (baseUrlPath, errorMessageHandler) { 
     this.STATUS_OK = 123; // trying to override. 
    }; 

// Declare HTTP response codes as constants 
Rest.prototype = { 
    get STATUS_OK(){ return 200; }, 
    get STATUS_BAD_REQUEST(){ return 400; } 
} 

var client = new Rest(); 
console.log(client.STATUS_OK); // 200! 
client.STATUS_OK = 123; 
console.log(client.STATUS_OK); // still 200! 

Thông tin thêm về getter và setter: http://ejohn.org/blog/javascript-getters-and-setters/

+0

'Object.defineProperty (Rest.prototype," STATUS_OK ", {get: function() {return 123;}});' và bạn ra ngoài :-) – Bergi

0

Javascript không có hỗ trợ tốt để tạo các hằng số không thể thay đổi. Ngay cả từ khóa const không được khuyến nghị vì không hoạt động trong một số trình duyệt.

Tôi nghĩ rằng con đường tốt nhất todo nó được sử dụng Object.freeze:

Rest.Status = {}; 
Rest.Status.Ok = "Ok"; 
Object.freeze(Rest.Status); 

Object.freeze sẽ im lặng bỏ qua những thay đổi trong đối tượng Trạng thái. Ví dụ:

Rest.Status.Ok = "foo"; 
Rest.Status.Ok; //=> "Ok" 

Nhưng chỉ làm việc trong ECMAScript 5 trở lên. Ở trên tôi đã đặt trạng thái trong một đối tượng Status, tôi nghĩ rằng nó thú vị hơn prototype, vì nguyên mẫu là gần gũi hơn với các phương pháp ví dụ, thuộc tính, vv Và đối tượng Trạng thái được xem như một liệt kê.

+0

Lưu ý rằng điều này vẫn cho phép gán lại thuộc tính 'Rest.Status' cho một đối tượng hoàn toàn khác. – apsillers

+0

Vâng, tôi đã không nhận ra nó. Một thay thế sẽ được tạo ra một đối tượng RestStatus, nhưng theo cách đó sẽ tồn tại hai biến toàn cục: ( –

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