面向对象的javascript中成员变量的最佳方法?

时间:2009-01-12 17:32:40

标签: javascript

这是我刚刚发布的问题的后续跟进。 我想知道在使用MyClass.prototype定义方法时,你们如何处理javascript clases中的成员变量。

如果在构造函数中定义所有方法:

function MyClass(){
 this.myMethod = function(){}
}

您可以很好地声明成员变量并从方法中访问它们:

function MyClass(){
 var myVar = "hello";
 this.myMethod = function(){
  alert(myVar);
 }
}

使用Object.prototype技术时,你会失去这种精确性,并且必须这样做;

function MyClass(){}
MyClass.prototype.myVar = "hello";
MyClass.prototype.myMethod = function(){alert(this.hello)};

每次访问成员变量时,我都不会写“this”。我想使用Object.prototype方法出于内存和灵活性的原因,但在语法方面看起来很笨拙。这是你们一般的工作方式吗?

感谢,

-Morgan

5 个答案:

答案 0 :(得分:18)

您应该克服使用this指针访问成员变量的厌恶。

在构造函数中分配成员变量,您可以使用原型方法访问它们:

function Cat(){
    this.legs = 4;
    this.temperament = 'Apathetic';
    this.sound = 'Meow';
}

Cat.prototype.speak = function(){alert(this.sound)}

var cat = new Cat();
cat.speak();

是的,这些对象属性是公开的,但正如Guido所说,我们都是成年人。毕竟,Javascript是一种纯文本,松散类型的解释语言。在这种环境中“私人”变量的好处充其量是不稳定的。

我说只是明确而明确地说明如何访问您的对象,违规者将自行承担风险。

答案 1 :(得分:15)

对象属性的可见性因您声明它们的方式而异

function Cat( name ) {

    //private variable unique to each instance of Cat
    var privateName = 'Cat_'+Math.floor( Math.random() * 100 );

    //public variable unique to each instance of Cat
    this.givenName = name;

    //this method has access to private variables
    this.sayPrivateName = function() {
        alert( privateName );
    }
}

//this variable is shared by all cats
Cat.prototype.generalName = 'tiddles';

//this method is shared by all cats and has no access to private vars
Cat.prototype.sayname = function( type ) {
    alert( this[type+'Name'] || 'private!' );
}

var vic = new Cat('Victor');
var ellers = new Cat('Elmore');

vic.sayname('general');    //tiddles
vic.sayname('given');      //Victor
vic.sayname('private');    //private - no access
vic.sayPrivateName();      //cat will say its name

ellers.sayname('general');    //tiddles
ellers.sayname('given');      //Elmore
ellers.sayname('private');    //private - no access
ellers.sayPrivateName();      //cat will say its name

答案 2 :(得分:3)

你应该使用原型来存储方法,因为当你发现自己有100个方法时,它们不会在实例之间复制,而是使用相同的原型。 我沿着这些方向使用了一些东西:

var myClass = function(){};
myClass.prototype = {
    method1: function(){}
    ,method2: function(){}   
};

答案 3 :(得分:2)

在为原型分配方法时,对'私有'变量的一个小的评论:

确实你不能使用构造函数来创建一个关于它的变量的闭包,但你当然可以用一个匿名函数包围原型方法并获得在对象实例之间共享的私有变量:

function Foo() {}

(function() {
    var sharedPrivateVar;
    Foo.prototype.methodWithAccessToSharedPrivateVar = function() {};
})();

通过进一步的讨论,您可以实现自己的保护机制,例如只能读取的变量,而不是通过以下方式写入:

function Foo() {
    this.registerInstance({ bar : 'baz' });
    this.registerInstance = undefined;
}

(function() {
    var store = {}, guid = 0;

    Foo.prototype.registerInstance = function(protectedProperties) {
        this.__guid = ++guid;
        store[this.__guid] = protectedProperties;
    };

    Foo.prototype.getProtectedProperty = function(name) {
        return store[this.__guid][name];
    };

})();

这种方法不会受到广泛的函数对象和闭包创建的影响,但会略微增加查找次数。

编辑:您还应提供功能

Foo.prototype.unregisterInstance = function() {
    delete store[this.__guid];
};

否则,这是引入内存泄漏的好方法......

Edit2:您还可以使用以下模式解决registerInstance()函数的需求:

Foo = (function() {
    var store = {}, guid = 0;

    function Foo() {
        this.__guid = ++guid;
        store[guid] = { bar : 'baz' };
    }

    Foo.prototype.getBar = function() {
        var privates = store[this.__guid];
        return privates.bar;
    };

    Foo.prototype.destroy = function() {
        delete store[this.__guid];
    };

    return Foo;
})();

答案 4 :(得分:-2)

你会发现很多人都在使用

function name()
{
    var m_var = null;
    var privateMethod = function() { }
    this.PublicMethod = function() { }
}

包括我自己。我倾向于不编写巨大的JS类,这种语法很容易编写,也允许使用私有方法/变量。

修改

所以你告诉我,使用XML进行SOAP数据包只是为了使调试更容易一步就好(即使XML浪费了空间和带宽的BUNCH,以及时间解析),但是每个javascript对象实例添加几个字节不是好吧,即使它允许我们使用从一开始就应该存在于语言中的一些有趣的OO概念?

嗯...

(我的XML评论阅读评论:REST URIs and operations on an object that can be commented on, tagged, rated, etc