2013-07-25 62 views
6

我正在使用RESTful API,並且我的Javascript代碼通過jQuery的$ .ajax()調用進行REST查詢。Javascript原型常量聲明

我實現了一個JavaScript的休息課,我將在下面顯示(大大簡化):

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"); 
       } 
      } 
     }); 
    }; 

代碼工作的預期,但我已經決定增加一些常量,幫助美化代碼和提高可讀性。例如,我在我的代碼中檢查了xhr.status == 200或xhr.status == 400等幾個地方。

我可以聲明類變量爲Rest.prototype.STATUS_OK = 200;

但變量是編輯,我想不出如何使他們不斷。在我的代碼例如,我可以做一個this.STATUS_OK = 123;,這將修改變量。我玩過const關鍵字,沒有運氣。

我看到這個:Where to declare class constants?,但它沒有太大的幫助。

有人能指出我在正確的方向,如何使這些領域的常量文字而不是變量?

+0

請注意,「字段」是*屬性*,而不是*變量*。對於變量,您可以在支持的地方使用['const' keyword](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)。但是無論如何,你會在本地範圍內:-) – Bergi

回答

8

使用ECMAScript 5的Object.defineProperty可以使一個值未設定:

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

或者說,這是因爲它們的默認值,簡單地做:

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

這使得Rest.STATUS_OK產量200訪問時,但它不會響應嘗試重新定義它或delete它。此外,configurable: false將阻止任何嘗試重新定義該財產與隨後的defineProperty電話。

但是,這在older browsers that don't support ES5's defineProperty(特別是IE8及以下版本)中不起作用。

+0

這是一個很好的解決方法,但它看起來像一個kludge必須寫幾行代碼(我知道它的一個陳述,但仍然有幾行可讀性)來設置一個常量。當你需要大量的常量來聲明時,肯定會做很多工作。隨着IE8及以下版本的逐步淘汰,未來可能會有更好的支持。 – Husman

+5

@Husman:其實你可以省略所有的行,但是'value',因爲'false'是默認值。 – Bergi

+0

@Bergi良好的通話;我根據你的建議編輯了我的答案。 – apsillers

1

這將無法在Javascript中使用。你也許可以做的最好的事情,就是創建一些封閉狀的東西:

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

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

}); 

而且使用它像StatusCode.getOk() === 200。這將幫助你無法改變這些'常量',但會再次對你的可讀性造成不利(這可能是基於觀點的)。 我只是將這些常量都保持爲大寫,將它們標記爲常量,儘管它們可以更改。

+1

+1;此外,沒有理由不能簡單地用'function(){return「別的東西」來覆蓋'getOk'; }'。 – apsillers

+1

@apillers好點。作爲底線,您無法安全地保護javascript中的任何內容。典型的例子 - 甚至可以覆蓋'undefined'。 –

1

您可以將狀態定義爲獲取者,但AFAIK在IE8及更低版本中不起作用。

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! 

更多關於getter和setter方法:http://ejohn.org/blog/javascript-getters-and-setters/

+0

'Object.defineProperty(Rest.prototype,「STATUS_OK」,{get:function(){return 123;}});'你就出來了:-) – Bergi

0

JavaScript沒有很好的支持來創建不可變的常量。 甚至不建議使用const關鍵字,因爲在某些瀏覽器中不起作用。

我認爲最好的辦法待辦事項它使用Object.freeze

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

Object.freeze將無聲忽略狀態對象的變化。 例如:

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

但就在ECMAScript中五或以上的工作。

上面我已經放在一個Status對象的狀態,我認爲它比prototype更有趣,因爲原型更接近於實例方法,屬性等 ,看到像一個枚舉狀態對象。

+0

請注意,這仍然允許將Rest.Status屬性重新分配給完全不同的對象。 – apsillers

+0

是的,我沒有意識到它。一種替代方法是創建一個RestStatus對象,但這種方式將存在兩個全局變量:( –