Javascript对象:如何创建包含封装的工作对象?

Javascript对象:如何创建包含封装的工作对象?,javascript,object,constructor,encapsulation,Javascript,Object,Constructor,Encapsulation,我想使用面向对象的Javascript,但我的“对象”的行为并不像我期望的那样 这是我的目标: var Test = function(a){ var variable = a; this.getA = function(){ return this.variable; } this.setA = function(a){ this.variable = a; } } 现在我运行以下代码: var a = new Te

我想使用面向对象的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”

如果要封装
a
的值,则不需要使用
this.variable
来访问该值,只需将
this.variable
更改为
variable
即可解决问题

变量具有功能范围,因此
var variable
定义了一个变量,该变量不仅适用于
Test
,也适用于
setA
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;
    }
}

如果要封装
a
的值,则不需要使用
this.variable
来访问该值,只需将
this.variable
更改为
variable
即可解决问题

变量具有功能范围,因此
var variable
定义了一个变量,该变量不仅适用于
Test
,也适用于
setA
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;
    }
}

JS中引用的任何
都将公开访问

但是,由于闭包的概念,只需在函数中声明变量(或函数),就可以拥有完全私有的状态

此外,除非您希望通过编码获得原型,否则您甚至不需要
新的
,也不需要
这个

例如:

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.age
是活着的

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\u接口
对象(这就是我返回的)

如果您开始使用
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 static
public static
(这是
prototype
最类似的)属性,但这在一开始就有点高级了,更让人困惑的是。

JS中引用的任何
都将公开访问

但是,由于闭包的概念,只需在函数中声明变量(或函数),就可以拥有完全私有的状态

此外,除非您希望通过编码获得原型,否则您甚至不需要
新的
,也不需要
这个

例如:

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.age
是活着的

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\u接口
对象(这就是我返回的)

如果您开始使用
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 static
public static
(这是
prototype
最类似的)属性,但这在一开始就有点高级了,有点让人困惑。

只是为了好玩(或者为了演示),我同时找到了另一个解决方案:

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
只是为了好玩(或为了演示),我同时找到了另一个解决方案:

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

你的期望是基于什么<代码>var变量
与该变量没有直接关系。变量
基于您的期望是什么
var变量
这个变量没有直接关系。变量
有趣的是,“this”有时会做什么-D非常感谢!“这个”有时真有趣-D非常感谢!难以置信,这正是我根本不懂的JS代码。也许我将来会学到这一点同时,我仍然使用“new”,因为这是自Javascript 1.2以来就存在的,并且是一个非常简单的方法+1用于在Javascript中使用快速数组。我个人将数组(JSON)用于数据结构(模型),而将普通对象用于控制器。虽然我看不出JS对象对于任何模型都有什么用途(好吧,数组也是对象,不是吗?),但我也看不出为什么命令“new”对于本地事件处理程序对象(“local”=浏览器中的永久对象)来说是件坏事