12

Javascript では、プロパティ アクセサーの使用はそれほど一般的ではないようです (Java などの他の OO 言語とは異なります)。

Person次のように定義された名前のオブジェクトがある場合

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

人の名前は変更されませんが、必要なときにアクセスできるようにしたいので、次のようにすることができます。

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

動的言語であっても、getter と setter を使用する原則は、静的に型付けされたオブジェクト指向言語 (カプセル化、検証の追加、アクセスの制限など) と同じように適用されると思います。

この質問は主観的なものとして閉じられるかもしれませんが、なぜこのような振る舞いが頻繁に見られないのか興味があります (たとえば、すべてが公開されていたら Java 開発者は頭がおかしくなるでしょう)。

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

4

5 に答える 5

15

Javascript には、インターセプト可能なプロパティ アクセサーがあります。

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

IMHOこれは、Javaのより厳密な明示的なゲッターよりもUniform Access Principleを実施するためのはるかに優れたソリューションですが、それはその言語の単純さと柔軟性の欠如の一部でもあります(たとえば、Groovyは同様の傍受を可能にします)。

于 2012-09-07T21:48:15.473 に答える
8

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

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

待って!本当!ちょっと待ってください。説明させてください。

メソッドを使用して値を取得および設定するだけでは、..まあ..ちょっと無意味です。それは実際には保護しません。

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

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 */ };
}

しかし、ほとんどの場合、静的データを押し込んで静的データを取り出すだけです。ゲッターとセッターの背後にそれを隠すポイントは何ですか?

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

于 2012-09-07T21:54:08.277 に答える
3

その答えは、javascript でクラスをエミュレートすることは一般的ではないということだと思います。言語は実際にはプロトタイプであるためです。

クラスのような構造を作成することは可能ですが (あなたの例のように)、それらは実際には Java クラスとは異なり、プログラマーとしてニュアンスと戦うことになります。

ただし、javascript のプロトタイプの性質を受け入れると、別の言語のまとまりのあるシンプルな構造が得られます。

プロトタイプ構造で getter と setter を使用する必要はありません。オブジェクトを値に設定するだけで簡単に設定でき、値として呼び出すことで取得できます。

Javascript は、構造化コードの記述を強制するものではなく、そうすることを妨げるものでもありません。JavaScript を中心に育った文化は、私が使用する他のどの言語とも異なる、完全に有効な優れたコーディング スタイルを開発したと思います。

この答えが決定的で決定的なものではないことはわかっていますが、探しているアンサーを見つけるのに役立ついくつかのアイデアがそこにあることを願っています.

于 2012-09-07T21:52:23.043 に答える
0

これは私がローカルフィールドに使用したものです:

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);
于 2015-05-16T10:41:48.007 に答える
0

質問を正しく理解していない場合は申し訳ありませんが、自己実行関数はメンバーを公開/非公開にする1つの方法です

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

その後、どこからでも Person.getName() にアクセスできますが、_name を設定することはできません。

于 2012-09-07T21:56:06.980 に答える