2012-09-07 5 views
11

Javascriptでは、プロパティアクセサーを使用するのはそのすべてではないようです(Javaなどの他のオブジェクト指向言語とは異なります)。javascriptのプロパティアクセサー

私は名前のPersonオブジェクトを持っている場合は、その人の名前を変更するつもりはないが、必要なときに、私はそれにアクセスできるようにしたいんので、私は何かができる

function Person(name) { 
    this.name = name; 
} 

として定義以下のような:

function Person(name) { 
    var name = name; 
    this.getName = function() { 
     return name; 
    } 
} 

でも動的言語では、私は(など、アクセスを制限、検証を追加するなどのカプセル化、)ゲッターとセッターを使用しての原則は、彼らが静的オブジェクト指向言語を入力する場合と同じ方法を適用すると思います

この質問は主観的に閉鎖されるかもしれませんが、なぜこの動作がより頻繁には表示されないのか不思議です(例: Java開発者はすべてが公開されていれば狂ってしまうだろう)。

javascriptでこれを行うための標準的な方法はありますか?私はObject.definePropertyを見ましたが、すべてのブラウザがそれをサポートしているわけではありません。

+0

帯域幅の負荷を軽減したいという趣旨に部分的に関係していると思われます。余分なマークアップとは、配線の余分なビットを意味します。このような小さな例の場合は、数万行に及ぶ堅牢なアプリケーションでは重要ではない可能性があります。 – Shmiddty

+0

余分な定義は、私の前のコメントと同じ行に沿って、クライアント上の余分なメモリ使用量を意味します。 – Shmiddty

+0

私はすでに回答が得られていると思いますが、意見に基づく回答を得やすいので、これは良い質問ではありません。実際には – madth3

答えて

15

Javascriptがインターセプト可能なプロパティアクセサがあります。これは、Javaのより厳格な明示的なゲッターよりも制服のアクセス原理を強制するはるかに良い解決策である

http://ejohn.org/blog/javascript-getters-and-setters/

私見を、それも単純化の一部であり、その言語の柔軟性がなくなります(Groovyは同様の傍受を許します)。

+0

、これはたくさん見られますか?または、通常、直接財産へのアクセスがありますか? –

+0

アクセサーロジックを変更する必要がない限り、直接プロパティアクセスを使用します。次に、インターセプトを使用します。彼らが何もしない場合、あなたはJavaでgetterとsetterを使用するのか?カプセル化の教義の背後にある実際の実際の理由は何ですか? –

+0

時には私は自分自身になぜか、特に単純な性質について尋ねます。理論的には、ゲッターやセッターでいくつかの動作を追加したいと思った場合(例えば、ログ、検証など)です。しかし実際には単純なプロパティではそれほど頻繁に起こるわけではないので、Javaのコンベンションのほうがはるかに優れています(getterとsetterを明示的に宣言していないが、ストレートプロパティアクセスの構文を書くことができます)。 –

3

私は、答えは、JavaScriptが実際にプロトタイプなので、javascriptのクラスをエミュレートするのが一般的ではないと思います。

クラスのような構造を作成することは可能ですが(例のように)、実際にはJavaクラスに似ていませんし、プログラマとしてはニュアンスを使って戦うことになります。

しかし、javascriptのプロトタイプの性質を受け入れるならば、あなたは言葉のための異なった、まだ一貫性のある、単純な構造で報われます。

ゲッターとセッターをプロトタイプ構造で使用する必要はありません。単純にオブジェクトを設定し、値を設定して取得し、値として呼び出すことができます。

Javascriptでは、構造化されたコードを強制的に記述することはありません。私はjavascriptの周りに成長した文化は、完全に有効で、私が使用する他の言語とは異なる、良いコーディングスタイルを開発したと思います。

私はこの答えが確定的ではなく、決定的ではないことを知っていますが、あなたが探しているアンサーを見つけるのに役立ついくつかのアイデアがあります。

+1

ありがとう。あなたはjavaで直接同じget/set値を行うことができます(例えば、物事をpublicにした場合)。しかし、それはぶつかるようです。私は言語のイディオムがどのようになっているのかと多くのことが関係していると思います。 –

+1

Javaの主な問題は、後でクラスのインタフェースを変更する必要がないことです。長期的なコード管理のために設計されたコンパイル言語であるため、急速に変化するWeb環境に配備されたソースベースの言語であるJSの優先順位とは異なります。 –

7

私は主題に関する私の考えを知っています。

ゲッターとセッターは悪です。

待機!本当に!私を抱きしめて説明しましょう。

値を取得して設定するメソッドを使用するだけで、まあまあ無意味です。それは本当に保護するものではなく、あなたが入れたものはあなたが出すものです。

一方、私は、情報を入れてから情報を取り戻す方法が好きです。しかしここには魔法の部分があります!それは同じ情報ではありません。直接ではありません。

function Person(name) { 
    this.getFullName = function() {return this.firstName + " " + this.lastName;}; 
    this.setBirthday = function(date) { this.birthday = date; }; 

    this.getAge = function() { /* Return age based on the birthday */ }; 
    this.isOfLegalDrinkingAge function() { /* do your math here too */ }; 
} 

しかし、ほとんどの場合、静的データを押し込んで静的データを取り出しているだけです。 getterとsetterの後ろに隠れている点は何ですか?

DOMとほとんどのホストオブジェクトを扱う第2の理由として、プロパティを設定します。ゲッターやセッターで遊んではいけません。それらを使用しないことは、JSコーダーが行うことの「味」の残りの部分に適合します。

+0

@BillyMoon - ユーザー名を「Javascript Preacher」に変更できるかどうか不思議。 –

+0

ありがとうございます。私はそれがJavaScriptの "味"ではないという事実は、私がここで得ているものだと思います。 –

+0

私の問題は、物事が機能かプロパティかどうか疑問です。場合によってはむしろ恣意的に見えることがあります。 Person.firstNameは動作しますが、Person.firstName()はPerson.fullNameの代わりにPerson.fullName()を使用する必要があります。 – CuddleBunny

0

私が正しく質問を理解しない場合、私は謝罪が、自己実行機能は、あなたはその後、どこからでもPerson.getNameを()へのアクセスが、_nameを設定することはできません

var Person = function(){ 
    var _name = "Roger", 
     self = { getName : function(){ return _name; }}; 
    return self; 
}() 

/秘密のメンバーが公開するための一つの方法です。

+1

私はあなたがこれを行うことができることを知っている、それは本当に一般的な練習ではないように思える... –

1

これは私が地元のフィールドに使用したものである:

TYPE_DEFAULT_VALUE= { 
    number: 0, 
    string: "", 
    array: [], 
    object: {}, 
}; 

typeOf = function (object) { 
    if (typeof object === "number" && isNaN(object)) 
     return NaN; 
    try { 
     return Object.prototype.toString.call(object).slice(8, -1).toLowerCase(); 
    } 
    catch(ex) { 
     return "N/A"; 
    }; 
}; 

getAccessor = function(obj, key, type, defaultValue) { 
    if (defaultValue === undefined) 
     defaultValue = TYPE_DEFAULT_VALUE[type] === undefined ? null : TYPE_DEFAULT_VALUE[type]; 
    return { 
     enumerable: true, 
     configurable: true, 
     get: function() { 
      if (obj[key] === undefined) 
       obj[key] = defaultValue; 
      return obj[key]; 
     }, 
     set: function (value) { 
      if (typeOf(value) === type) 
       obj[key] = value; 
     }, 
    }; 
} 

LocalFields = function (fields, object) { 
    /** 
    * field properties 
    * { 
    * type: [ required ] (number | string | array | object | ...), 
    * defaultValue: [ optional ] 
    * } 
    */ 
    if (! fields) 
     throw "Too few parameters ..."; 
    if (! object) 
     object = this; 

    var obj = this; 
    var fieldsAccessor = {}; 
    for(key in fields){ 
     field = fields[key]; 
     fieldHandler = key[0].toUpperCase() + key.substr(1); 
     if(! field.type) 
      throw "Type not set for field: " + key; 

     fieldsAccessor[fieldHandler] = getAccessor(obj, fieldHandler, field.type, field.defaultValue) 
    } 
    Object.defineProperties(object, fieldsAccessor); 
} 

は今、各クラスのために私はちょうどのようなものを呼び出すことができます。

Person = function(){ 
    new LocalFields({ 
     id:  { type: "number" }, 
     name: { type: "string" }, 
    }, this); 
} 

をそしてVSゲッターとセッターのように、あなたは呼ぶことにします:

var alex = new Person(); 
alex.Name = "Alex Ramsi"; 
console.clear(); 
console.info(alex.Name);