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.variable来访问该值,只需更改this.variable为即可variable解决问题。

变量具有函数作用域,因此var variable定义了一个变量,该变量不仅在 for 范围内Test,而且在 for setAand范围内getA

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内容都将可公开访问。

但是,由于闭包的概念,您可以拥有一个完全私有的状态,只需在函数内部声明变量(或函数)。

此外,除非您希望通过编码获得原型,否则您甚至不需要new, 那里,也不需要this.

一个例子:

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.namesecret.age也不is_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`

任何未在函数内部定义函数都无法访问内部属性或方法。

您可以以完全相同的方式拥有私有方法——事实上,所有这些函数都是私有的,直到我将它们全部附加到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, private,private staticpublic 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 回答