Information hiding when using the prototype object
In our code base, I find that many developers use underscores as the first letter of a member variable to discourage public use. Normally, a better practice is just to declare a local variable that's accessible to an object's methods, but in our case, this doesn't seem possible because all the methods are defined on the prototype. Here's an example.
MyContrivedWidget = function(container) {
this._container = jQuery(container);
}
MyContrivedWidget.prototype = {
draw: function() {
var link = jQuery(document.createElement('a'))
.html('some contrived text')
.attr('href', '#')
.appendTo(this._container);
}
}
We have multiple reasons for using the prototype obje开发者_StackOverflow中文版ct, but the most compelling is probably that using the prototype chain allows for easy inheritance and overriding of methods. This is good for us because we have multiple products on one platform that may want to reuse a lot of JavaScript while overriding specific functionality.
So my question is, how can we get all the benefits of the prototype chain without allowing variables that should be private to be publicly accessible?
Simply spoken: ECMAscript edition 3 has no possibility to create "private" variables using prototypal inheritance or the prototype chain.
It's a little different in ES5. You've got methods like .defineProperties()
help there which, are able to "hide" properties within an object.
But even if you hide the propertys from enumaration for instance, one would still be able to access those if he knows they are available. As you mentioned, the only real privacy in ECMAland is, to invoke closures. Better said, using a method-pattern by invoking a function(-context) which returns an object that contains methods as propertys. Those methods have access (since it's context closes over the parent context) to the declared variables in the outer (parent) scope. No other object can access those variables after. This looks like:
var Animal = function( args, priv, shared ) {
shared = shared || { };
shared.speed = 2;
shared.legs = 4;
shared.name = args.name || 'unknown';
priv = priv || {
run: function() {
console.log(shared.name, ' is running ', shared.speed, ' meters');
return this;
},
die: function() {
console.log(shared.name, ': wwuuaarhhhck.. aahahsd sd..aahsd.....');
return this;
}
};
return priv;
};
var Dog = function( args, priv, secret ) {
secret = secret || { };
priv = Animal( args, priv, secret ) || { };
priv.addSomeMethod = function() { };
return priv;
};
var bello = Dog({name: 'Bello'});
bello.die(); // "Bello: wwuuaarhhhck.. aahahsd sd..aahsd....."
There are some great patterns out there which bring this idea to an extend, which are also offer inheritance and shared objects + super methods. A good start to this kind of programming is still Douglas Crockfords "Javascript: the good parts".
精彩评论