2013-07-25 12 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'キーワード](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

これは良い回避策ですが、単一の定数を設定するために、いくつかの行のコードを書く必要があります(私はその1つのステートメントを知っていますが、読みやすくするためにいくつかの行があります)。宣言する定数がたくさんあるときは、確かに多くの仕事があります。おそらく、IE8以降が段階的に廃止されるため、将来的にはこれに対するより良いサポートがあるでしょう。 – Husman

+5

@Husman:実際には、 'false'はそれらのデフォルトであるので、' value'以外のすべての行を省略することができます。 – 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" something else ";}で' getOk'を上書きすることができない理由はありません。 } '。 – apsillers

+1

@apsillers良い点。結論として、あなたは安全に何かを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! 

より: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を使用している最良の方法のTODOを考える:

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

Object.freezeはStatusオブジェクトの変更をサイレント無視します。

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

しかし、単にのECMAScript 5でまたは上記の作業:例により、 。

私はStatusオブジェクト内の地位を配置した上、私はプロトタイプがインスタンスメソッド、プロパティなど 列挙のように見えるStatusオブジェクトに、より近いので、それは、prototypeよりも面白いと思います。

+0

これは、 'Rest.Status'プロパティの完全に別のオブジェクトへの再割り当てを可能にすることに注意してください。 – apsillers

+0

はい、私はそれを実現していません。 1つの方法はRestStatusオブジェクトを作成することですが、その方法では2つのグローバル変数が存在します: –

関連する問題