0

オブジェクト指向の Javascript を使用したいのですが、「オブジェクト」の動作が期待どおりではありません。

これは私の目的です:

var Test = function(a){
    var variable = a;

    this.getA = function(){
        return this.variable;
    }

    this.setA = function(a){
        this.variable = a;
    }
}

今、私はこのコードを実行します:

var a = new Test("foo");
var b = new Test("bar");

alert(a.getA());                //undefined, but "foo" expected
alert(a.getA() == b.getA());    //true, but false expected

alert(a.variable);              //undefined, as expected

a.variable = "whatever";
alert(a.getA());                //"whatever", but undefined expected
alert(a.variable);              //"whatever", but undefined expected

a.setA("somewhere");
alert(a.getA());                //"somewhere", as expected
alert(a.variable);              //"somewhere", but undefined expected

最初に "setA(a)" を呼び出す必要がなく、オブジェクトのカプセル化で a.variable = "whatever"; を許可せずに、機能するオブジェクトを作成する方法を知っている人はいますか?

4

3 に答える 3

2

の値をカプセル化している場合、値にアクセスするaために を使用する必要はありません。単に に変更するだけで問題が解決します。this.variablethis.variablevariable

変数には機能スコープがあるため、var variableだけでなく と のスコープにもある変数を定義します。TestsetAgetA

var Test = function(a){
    var variable = a;

    this.getA = function(){
        //you want to access the variable,
        //not the property on the instance
        return variable;

    }

    this.setA = function(a){
        variable = a;
    }
}
于 2013-02-03T03:11:26.880 に答える
1

JS で参照されるものはすべてthis公開されます。

ただし、クロージャーの概念のおかげで、関数内で変数 (または関数) を宣言するだけで、完全にプライベートな状態にすることができます。

さらに、コーディングでプロトタイプを作成しようとしている場合を除き、 も必要ありませnewthis

例:

var makePerson = function (secret) {

    var is_alive = true,

        sayName = function () {
            if (!is_alive) { return; }
            console.log("My name is " + secret.name + ".");
        },

        sayAge = function () {
            if (!is_alive) { return; }
            console.log("My age is " + secret.age + ".");
        },

        haveBirthday = function () {
            if (!is_alive) { return; }
            secret.name += 1;
            console.log("I'm " + secret.name + 
                        ", and today I turned " + secret.age + ".");
        },

        die = function () {
            is_alive = false;
            console.log(secret.name + " died today;" +
                        " they were " + secret.age + " year" +
                        (secret.age > 1 ? "s" : "") + " old."   );
        },

        public_interface = { sayName      : sayName,
                             sayAge       : sayAge,
                             haveBirthday : haveBirthday,
                             die          : die           };

    return public_interface;
};


var bob = makePerson({ name : "Bob", age : 32 });

誰も触れたりsecret.name、外から触れたりすることはできません。secret.ageis_alive

bob.name; // undefined
bob.is_alive = false;  // Doesn't matter -- the code isn't relying on a public property.


bob.sayAge();       // "My age is 32"
bob.haveBirthday(); // "I'm Bob, and today I turned 33"
bob.die();          // "Bob died today; they were 33 years old"

さらに良いことに、JS ではいつでも割り当てを変更できるため、次のような心配があるかもしれません。

// person overwriting the function
bob.haveBirthday = function () { is_alive = false; };

...しかし、誰かがそれを行うことを恐れる理由はまったくありません。彼らはそれらの内部プロパティにアクセスできないからです。

bob.haveBirthday(); // window.is_alive = false;
bob.sayAge(); "My age is 33";

同様に、値を盗むように関数を書き直そうとすると、次のようになります。

bob.sayName = function () { return secret.name; };
bob.sayName(); // window.secret.name;  OR  ERROR: can't call `name` of `undefined`

関数のINSIDEで定義されていない関数は、内部プロパティまたはメソッドにアクセスできません。

また、まったく同じ方法でプライベート メソッドを使用することもできます。実際、これらの関数はすべて、public_interfaceオブジェクトにすべてアタッチするまではプライベートでした (これが返されました)。

を使い始める場合は、これを覚えておくことが重要ですprototype

var Thing = function (secret) {};
Thing.prototype.sayName = function () { console.log("My name is " + secret.name); };
var thing = new Thing({ name : "Bob", age : 32 });

thing.sayName(); // "My name is undefined"

プロトタイプ関数でさえ、プライベート状態にアクセスできません。パブリック状態を使用する必要があります (を介してthis)。

public複数のクロージャに、privateprivate staticおよびpublic static(これが最も似ている) プロパティを持たせる、より複雑な構造を使用できますが、これはprototype少し高度で、最初は少し混乱します。

于 2013-02-03T03:48:16.530 に答える
0

楽しみのために(またはデモンストレーション目的で)、その間に別の解決策を見つけました:

var Test = function(x){
    var variables = function(){}
    variables.variable = x; 

    this.getA = function(){
        return variables.variable;
    }

    this.setA = function(x){
        variables.variable = x;
    }
}

テスト結果:

    var a = new Test("foo");
    var b = new Test("baz");

    alert(a.getA());                //"foo" as expected
    alert(a.getA() == b.getA());    //false as expected

    a.variable = "whatever";
    alert(a.getA());                //"foo" as expected
    alert(a.variable);              //"whatever", doesn't seem preventable

    a.setA("somewhere");
    alert(a.getA());                //"somewhere", as expected
    alert(a.variable);              //"whatever", doesn't seem preventable
于 2013-02-03T04:30:33.857 に答える