Reputation: 6909
I am working with a RESTful API, and my Javascript code is making REST queries via jQuery's $.ajax() call.
I have implemented a javascript Rest class, which I will show below (greatly simplified):
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");
}
}
});
};
The code works as intended, however I have decided to add some constants to help beautify the code and improve readability. I have for example several places in my code where I am checking for xhr.status == 200 or xhr.status == 400 and so on.
I can declare class variables as Rest.prototype.STATUS_OK = 200;
But variable is editable, and I cannot think of how to make them constant. In my code for example I can do a this.STATUS_OK = 123;
and this will modify the variable. I have played around with the const keyword, with no luck.
i have seen this: Where to declare class constants?, but it was not much help.
Can someone point me in the right direction as to how to make these fields a constant literal instead of a variable?
Upvotes: 8
Views: 10089
Reputation: 19128
Javascript doesn't have a good support to create immutable constants. Even the const keyword isn't recommended because doesn't work in some browsers.
I think the best way todo it is using Object.freeze
:
Rest.Status = {};
Rest.Status.Ok = "Ok";
Object.freeze(Rest.Status);
Object.freeze will silent ignore changes in the Status object. By example:
Rest.Status.Ok = "foo";
Rest.Status.Ok; //=> "Ok"
But just work in ECMAScript 5 or above.
Above I have placed the status in a Status
object, I think that it is more interesting than prototype
, because prototype is more close to instance methods, properties etc.
And the Status object seen like a enumeration.
Upvotes: 0
Reputation: 115940
Using ECMAScript 5's Object.defineProperty
you can make a value un-settable:
Object.defineProperty(Rest, "STATUS_OK", {
enumerable: false, // optional; if you care about your enumerated keys
configurable: false,
writable: false,
value: 200
});
Or, since those are the default values, simply do:
Object.defineProperty(Rest, "STATUS_OK", { value: 200 });
This makes Rest.STATUS_OK
yield 200
when accessed, but it will not respond to attempts to redefine it or delete
it. Furthermore, configurable: false
will prevent any attempt to redefine the property with a subsequent defineProperty
call.
However, this doesn't work in older browsers that don't support ES5's defineProperty
(notably IE8 and below).
Upvotes: 13
Reputation: 36965
You could define the statuses as getters, but AFAIK this won't work in IE8 and older.
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!
More on getters and setters: http://ejohn.org/blog/javascript-getters-and-setters/
Upvotes: 1
Reputation: 14465
This will not be possible in Javascript. Best thing you could probably do, is create some closure like stuff:
var StatusCode = (function() {
var STATUS_OK = 200,
STATUS_BAD_REQUEST = 400;
return {
getOk: function() {
return STATUS_OK;
},
getBadRequest: function() {
return STATUS_BAD_REQUEST;
}
}
});
And use it like StatusCode.getOk() === 200
. This would help you to not be able to change those 'constants', but will again be bad for your readability (this is probably opinion based).
I would just keep those constants all uppercase to mark them as constant, although they could be changed.
Upvotes: 2