Encapsulating in JavaScript, does it exist?

前端 未结 4 951
予麋鹿
予麋鹿 2021-01-07 00:03

I have an experience with the C# programming language, but I also have to work with the JS now and it\'s rather new for me.

I have tried to develop a simple class em

4条回答
  •  礼貌的吻别
    2021-01-07 00:50

    If you want to use inheritance, you cannot (at least AFAIK). For objects with no inheritance chain you can however use closures to get exactly the same effect. The question is if you actually really need properties to actually be completely private.

    The closures approach

    You can execute a function of which closure contains the variables you want to be private. These private variables do not actually belong to the object, but are only accesible by the methods of the object. For instance:

    var getPersonInstance = function (name) {
    
        // Those are "private" properties
        var myName = name;
    
        return {
            getName: function () {
                return myName
            },
            setName: function (name) {
                myName = name;
            },
            sayHello = function () {
                alert('hello! my name is ' + myName);
            }
        }    
    };
    
    var person = getPersonInstance('Juan');
    person.getName(); // Returns Juan
    person.myName = 'Don Vito' // This sets the person.myName property, which is not the one in the closure
    person.setName('John') // Works
    person.sayHello(); // alert hello! my name is John
    

    You can check it out here:

    http://jsfiddle.net/MLF7v/1/

    If you feel more comfortable with the Constructor function notation, you can do something like this:

    (Not tested)

    function Person(name) {
        // Anything that is not attached to this will be private
        var myName = name;
    
    
        this.getName = function () { return myName;};
        this.setName = function (newName) {myName = newName;};
        this.sayHello = function () {alert('hey there, my name is' + myName);};
    }
    

    Which is pretty much the same as above, since the prototype is not used and the methods are copied directly into the object.

    However, the closure approach are is memory and time consuming, and the worst: they make use of variables that do not in fact belong to the object you are working with... This is an important "semantic" problem (does this prop belong to me, or not?) that makes inheritance a headache. The reason for this, is that the methods of the extended objects either dont have access to that private pseudo-property (because they are not defined in the superobject closure), or have access to a common private variable from the "superobject" (the method was defined in the superobject and therefore access the closure of the superobject). That is a nonsense.

    The "cultural" approach

    In my humble opinion, encapsulation does not prevent anybody from messing with your code if he/she really wants to, so I prefer to follow the python philosophy "we are all mature people" which consists of using a convention to say "I would like this property not to be used from the outside". For instance, I prefix the private properties with '_', meaning that they're private, protected, or whatever but just stay away from it. And you don't touch what you should not touch.

    This approach, appart from being the simplest and the most efficient, allows you for working with inheritance chains, since the properties are in the object and not confined in the closure.

    var Person = function (name) {
        this._name = name;
    }
    Person.prototype.sayHello = function () {...};
    Person.prototype.getName = function () {...};
    Person.prototype.setName = function () {...};
    

提交回复
热议问题