我正在使用RESTful API,我的Javascript代码通过jQuery的$ .ajax()调用进行REST查询。
我已经实现了一个javascript Rest类,我将在下面展示(大大简化):
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 :(得分:10)
使用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及以下版本)。
答案 1 :(得分:2)
这在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
一样使用它。这将有助于您无法更改这些常量,但会再次对您的可读性造成不利影响(这可能是基于意见的)。
我只是将这些常量保持为大写以将它们标记为常量,尽管它们可以更改。
答案 2 :(得分:1)
您可以将状态定义为getter,但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/
答案 3 :(得分:0)
Javascript没有很好的支持来创建不可变的常量。 建议不要使用const关键字,因为在某些浏览器中不起作用。
我认为最好的办法就是使用Object.freeze
:
Rest.Status = {};
Rest.Status.Ok = "Ok";
Object.freeze(Rest.Status);
Object.freeze将静默忽略Status对象中的更改。 例如:
Rest.Status.Ok = "foo";
Rest.Status.Ok; //=> "Ok"
但只需在ECMAScript 5或以上版本中工作。
上面我已将状态放在Status
对象中,我认为它比prototype
更有趣,因为原型更接近实例方法,属性等。
并且Status对象看起来像枚举。