Encapsulation in JavaScript with protoypes - javascript

Probably many of you tried to achieve encapsulation in JavaScript. The two methods known to me are:
a bit more common I guess:
var myClass(){
var prv //and all private stuff here
//and we don't use protoype, everything is created inside scope
return {publicFunc:sth};
}
and second one:
var myClass2(){
var prv={private stuff here}
Object.defineProperty(this,'prv',{value:prv})
return {publicFunc:this.someFunc.bind(this)};
}
myClass2.prototype={
get prv(){throw 'class must be created using new keyword'},
someFunc:function(){
console.log(this.prv);
}
}
Object.freeze(myClass)
Object.freeze(myClass.prototype)
So, as second option is WAY more convenient to me (specifically in my case as it visually separates construction from workflow) the question is - are there any serious disadvantages / leaks in this case? I know it allows external code to access arguments of someFunc by
myClass.protoype.someFunc.arguments
but only in case of sloppily executed callbacks (synchronously inside caller chain). Calling them with setTimeout(cb,0) breaks chain and disallows to get arguments as well as just returning value synchronously. At least as far as i know.
Did I miss anything? It's kind of important as code will be used by external, untrusted user provided code.

I like to wrap my prototypes in a module which returns the object, this way you can use the module's scope for any private variables, protecting consumers of your object from accidentally messing with your private properties.
var MyObject = (function (dependency) {
// private (static) variables
var priv1, priv2;
// constructor
var module = function () {
// ...
};
// public interfaces
module.prototype.publicInterface1 = function () {
};
module.prototype.publicInterface2 = function () {
};
// return the object definition
return module;
})(dependency);
Then in some other file you can use it like normal:
obj = new MyObject();
Any more 'protecting' of your object is a little overkill for JavaScript imo. If someone wants to extend your object then they probably know what they're doing and you should let them!
As redbmk points out if you need private instance variables you could use a map with some unique identifier of the object as the key.

So, as second option is WAY more convenient to me (specifically in my case as it visually separates construction from workflow) the question is - are there any serious disadvantages / leaks in this case?
Hm, it doesn't really use the prototype. There's no reason to "encapsulate" anything here, as the prototype methods will only be able to use public properties - just like your untrusted code can access them. A simple
function myClass2(){
var prv = // private stuff here
Object.defineProperty(this, 'prv', {value:prv})
// optionally bind the publicFunc if you need to
}
myClass2.prototype.publicFunc = function(){
console.log(this.prv);
};
should suffice. Or you use the factory pattern, without any prototypes:
function myClass2(){
var prv = // private stuff here
return {
prv: prv,
publicFunc: function(){
console.log(this.prv); // or even just `prv`?
}
};
}
I know it allows external code to access arguments of someFunc by
myClass.protoype.someFunc.arguments
Simply use strict mode, this "feature" is disallowed there.
It's kind of important as code will be used by external, untrusted user provided code.
They will always get your secrets if the code is running in the same environment. Always. You might want to try WebWorkers instead, but notice that they're still CORS-privileged.

To enforcing encapsulation in a language that doesn't properly support private, protected and public class members I say "Meh."
I like the cleanliness of the Foo.prototype = { ... }; syntax. Making methods public also allows you to unit test all the methods in your "class". On top of that, I just simply don't trust JavaScript from a security standpoint. Always have security measures on the server protecting your system.
Go for "ease of programming and testing" and "cleanliness of code." Make it easy to write and maintain, so whichever you feel is easier to write and maintain is the answer.

Related

Is it possible to spy on or mock the value of a "behind-the-scenes" variable?

Let's say I have code that modifies a variable which is not exposed to the user like this:
var model;
module.exports = {
doSomething: function() {
...
//at some point in the code, modify model
if(/* something happened */) {
model = '123';
},
doSomethingElse: function() {
//use model in some way
}
}
};
If I later want to write a unit test to make sure that model was updated, but I do not have a getter for it, how can I test this? Is this possible to do with Karma/Jasmine/Sinon.js?
It is impossible to check the model value directly because it's hidden in a closure.
You can still write tests for it though: Your "model" will make doSomethingElse behave differently. You can verify that it matches your expectations after calling doSomething. This way, you are also free refactor the internals of your module without changing the test cases.
In general, testing private methods or properties is an antipattern. By making aspects of your implementation private, you're explicitly creating the freedom to change how those implementation details work in the future without changing your public API.
Therefore, in an ideal world, you should not (and in this case, you cannot) test the model value.
That said, we don't always live in an ideal world. So, there are some workarounds that you might consider if you really, really must test private properties and methods.
First, you could look for an environment variable, and export additional properties (by attaching them to the exports).
var model;
module.exports = {
...
}
if(process.env.ENV === 'TEST') {
module.exports.model = model;
}
Second, you can use conventions instead of making things completely private. For example, a common convention is to prefix private entities with _ to signify that they are not part of the public API. This can have varied levels of effectiveness depending on the audience that will consume your API.
Third, you could create accessors for your private variables, and check for the presence of a testing environment in some way (perhaps a global variable, an environment variable, or a variable injected into your module upon instantiation) that only allows access when the test environment is detected.
Fourth, you could allow an "inspector" object to be injected into your module (this object would only be present during testing). I have used this pattern with some success.
module.exports = function(spies) {
...
spies = spies || {};
var model = spies.model;
...
}
...
// instantiate the module in the test
var spies = {};
var mock = new Module(spies);
// do a thing
expect(spies.model).to.eql("foo");
But really, you should reconsider your testing strategy and design.

Javascript 'normal' objects vs module pattern

Currently I'm developing a large scale Javascript app(single page) and I've searched around the web to find some best practices. Most projects use the module pattern so the objects doesn't pollute the global namespace. At this moment I use normal objects:
function LoginModel(){
this.model = new MyModel();
this.getModel = function(){
return this.model;
};
}
This is readable and easy to maintain(my opinion). Is it better to use the module pattern just because of the namespacing or does it has other advantages I'm not aware of(counter memory leaks, ... )? Furthermore, I've already splitted up the files to have a nice MVC pattern and destroy every object when needed(counter memory leaks). So the main question is: do I need, in my case, to use the module pattern or not?
Module pattern:
var LoginModel = (function(){
var model = MyModel;
function getModel(){
return model;
};
return {
getModel: getModel
};
});
The module pattern is better for overall code organization. It lets you have data, logic and functions that are private to that scope.
In your second example getModel() is the only way to get the model from the outside. The variable declared int he module are hidden unless explicitly exposed. This can be a very handy thing.
And there's not really any drawback, other than being a little more complex. You just get more options for organization and encapsulation.
I'd use a plain object until my model gets complex enough to need more structure and some private scoping. And when you hit that point, it's trivial to redefine it as a revealing module without breaking any of the code that uses it.
If you're only going to be using one instance per page, I don't see the need to involve the new keyword. So personally I would create a revealing module like you did in your last example, and expose an object with the "public" properties.
Though I don't see your point with the getModel() function, since MyModel is obviously accessable outside of the scope.
I would have rewritten it slightly:
var LoginModel = (function(model, window, undefined){
function init(){ } // or whatever
function doSomethingWithModel(){
console.log(model);
}
return { init: init };
})(MyModel, window);
If you're uncertain of which modules that will get a model, you can use loose augumentation and change
})(MyModel, window);
to
})(MyModel || {}, window);
If you need several instances of a module, it would look something like this:
var LoginModel = (function(model, window, undefined){
function loginModel(name){ // constructor
this.name = name; // something instance specific
}
loginModel.prototype.getName = function(){
return this.name;
};
return loginModel;
})(MyModel, window);
var lm1 = new LoginModel('foo');
var lm2 = new LoginModel('bar');
console.log(lm1.getName(), lm2.getName()); // 'foo', 'bar'
There's several concepts conflated in your question
With what you call the "normal object", the function becomes a constructor function and requires the new keyword.
The second example uses the Revealing Module Pattern inside of an IIFE. This is the most popular variant of the Module Pattern, but unfortunately deeply flawed. For an explanation of the differences see my answer here, and for its flaws, see here.
Now, your question poses a false dichotomy -- normal objects or module pattern? You don't have to make a choice -- a normal object can use the module pattern simply by putting whatever it wants to keep private inside its closure scope. For example,
function LoginModel(){
var _notifyListeners = function(){
// Do your stuff here
};
this.model = new MyModel();
this.getModel = function(){
_notifyListeners();
return this.model;
};
}
This is an example of a "normal object" using the module pattern. What you have to avoid doing is what the Revealing Module Pattern does -- putting everything into closure scope. You should only put the things you want to keep private inside the closure scope.

Javascript "priveleged" methods that are not re-created per object?

When looking around for emulating private methods from other languages, commonly Crockford's page is suggested that proposes this "priveleged" method:
function Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
this.service = function () {
return dec() ? that.member : null;
};
}
So service is priveleged - it can access private methods (like dec) and private variables (like secret). I assume it can also call "public" methods (those assigned to Container.prototype).
However, isn't service re-created for every object of new Container? Doesn't it take extra time and consume extra memory? And the private dec too, for that matter.
I understood that the recommended JS way to make methods is on KlassFunction.prototype to avoid this performance problem. But can non-public methods be created this way at all?
There is really two kinds of private.
The kind of private rigorously enforced in runtime. This always has a runtime penalty of course. Here private is used as a security mechanism. Completely useless in Javascript.
The private to signal your interface to other developers that is not obviously enforced at runtime. You can still
access fields if you want using reflection. Here private is used to prevent accidental misuse of class internals.
If I guess correctly, you are trying to achieve the second goal by doing the first. The second goal can be achieved
simply by conventions and enforcing those conventions in your build step. There is no need to take that into the runtime.
The memory use (pressure put on GC actually) is not the only problem, the closure class pattern is incredibly inflexible in that you cannot reuse, share or inherit
the functions in any way. And you cannot access the variables outside even for temporary reasons. Also read http://blog.jcoglan.com/2012/01/19/the-cost-of-privacy/

Aliasing a function object in JavaScript

Disclaimer: I am using ExtJS 3, but I don't think it's very relevant to the question, outside of the common use of it's namespacing function.
I have a singleton that's declared in a really long namespace like this:
Ext.ns("REALLY.REALLY.LONG.NAMESPACE");
var Singleton = (function() {
var foo = {
bar: "baz"
};
var privateFunction = function(param){
// ...
return foo;
};
var single = Ext.extend(Object, {
constructor: function(config) {
Ext.apply(this, config);
},
otherFunction: privateFunction,
publicFunction: function (someObject){
// do stuff with someObject
}
});
return single;
})();
// Make it a singleton
REALLY.REALLY.LONG.NAMESPACE.Singleton = new Singleton();
I use it in other modules via calls like REALLY.REALLY.LONG.NAMESPACE.Singleton.otherFunction(); and REALLY.REALLY.LONG.NAMESPACE.Singleton.publicFunction(myObject); . I'm wondering if I can swap out those calls by setting up the client module with an alias to the singleton, i.e. var singleton = REALLY.REALLY.LONG.NAMESPACE.Singleton; , so that I can call singleton.otherFunction();. I'm wondering if this is an anti-pattern , or if there are any pitfalls (memory?) I might run into through this usage.
Thanks StackOverflow!
I'm wondering if I can swap out those calls by setting up the client module with an alias to the singleton
Yes, you can.
I'm wondering if this is an anti-pattern , or if there are any pitfalls (memory?) I might run into through this usage.
No, there aren't any that I can think of and it is faster than calling the fully-qualified version.
Local Alias Pattern
Example:
function somefunc(){
var singleton = REALLY.REALLY.LONG.NAMESPACE.Singleton;
singleton.publicFunction();
};
Or:
(function somfunc(singleton){
}(REALLY.REALLY.LONG.NAMESPACE.Singleton));
Test Results:
http://jsfiddle.net/jMg9A/
There is no issue with creating a reference to the original "object". In many cases we create a namespace to organize our code, but of course, this can lead to really long namespaces that we really don't wish to reference later, thus creating a local reference to that namespace is an excellent idea so that you can change it in one place instead of various places.
I don't really see an ant-pattern here, instead I see an opportunity to make it simpler for yourself and probably a little more manageable from a developer standpoint.

How do I mimic access modifiers in JavaScript with the Prototype library?

I've been working with the prototype library for some time now and occasionally find myself wishing I had multiple access levels (public, private, and protected). The closest I've come so far is the following:
SampleBase = Class.create({
/* virtual public constructor */
initialize: function(arg1, arg2)
{
// private variables
var privateVar1, privateVar2;
// private methods
var privateMethod1 = function() { }
function privateMethod2() { }
// public (non virtual) methods
this.publicNonVirtual1 = function() { return privateVar1; }
this.publicNonVirtual2 = function() { return privateVar2; }
},
// public methods (that cannot access privates)
publicVirtual1: function() { /* Cannot access privates here. */ },
publicVirtual2: function() { /* Cannot access privates here. */ }
});
This less then ideal for several reasons:
No protected level
I can have public members that can access private members or public members that can be overridden but not not public member that can access private members and be overridden.
My public methods that can be overridden are not prototyped.
I've done some searching but haven't found anything that suggests I can do better without altering how prototype works. Here's some of the more interesting links:
Using Prototype’s Class.create to define private/protected properties and methods
JavaScript private methods
Private Members in JavaScript
Again with the Module Pattern – reveal something to the world
I've seen it suggested that you can provide accessors for my public virtual methods to use by doing something like this:
Message = Class.create({
initialize: function(message)
{
var _message = message;
this.getMessage = function() { return _message; }
this.setMessage = function(value) { _message = value; }
},
printMessage: function() { console.log(this.getMessage()); },
appendToMessage: function(value) { this.setMessage(this.getMessage() + value); }
});
This clearly will not work as intended. The goal is to only allow printing and appending to the message from outside of the object. The setter provided to make the virtual public function work also allows full control of the message. It could be changed to make the virtual method little more then a shell as follows:
Message = Class.create({
initialize: function(message)
{
var _message = message;
this._printMessage = function() { console.log(_message); }
this._appendToMessage = function(value) { _message += value; }
},
printMessage: function() {this._printMessage(); },
appendToMessage: function(value) { this._appendToMessage(value); }
});
This new version does limit public access for this class but is somewhat redundant. Not to mention if appendToMessage is overriden in a subclass a third party can still call _appendToMessage to access the original method which is not good.
I do have a very dirty idea that will get me close but is a can of worms I'd rather not open. I may post it later but in the mean time does anyone have suggestions for merging the two types of public methods into one useful type or on how to implement protected members.
EDIT:
I suspect the lack of feedback (aside from bobince's don't bother comment) mean that I am correct in that you can't take it any farther but I think I'll clarify a little just in case. I don't think it is possible to get anything close to the protection of other languages. I'm more interested in knowing where the limits lie and how accurate my understanding of the principles involved are. I do however think it would be interesting, if not useful, if we could get the various protection levels functioning to the point that non public members don't show up in a for...in loop (or in Prototypes Object.keys which uses for..in) even if it people who know what they are doing can still break the rules by doing things like tinkering with my prototypes. Afterall, its like bobince says " they have no-one to blame but themselves"
Now to comment on an issue raised by bobince:
Even if you made real
private/protected variables it still
wouldn't get you the full
encapsulation an effective security
boundary would require. JavaScript's
ability to fiddle with the prototypes
of built-in types your methods will be
using gives an attacker the ability to
sabotage the methods.
This is one limitation I do understand and I probably should have mentioned above. However, I am not looking at this from the point of view of protecting my code from someone trying to "hack" it. However, I do have a few things that may be worth noting (or in need of correcting if I am wrong):
Only my public members are vulnerable in this way.
If my public virtual methods are "compromised" in this way, then the "compromised" methods will still not have access to the private members.
If my public (non virtual) members are "compromised" in this way, then, unlike the original version of the method, the "compromised" version will not have access to the private memebers.
As far as i know the only way to gain accesses to the private members by methods defined outside of initialize method is too take advantage of a bug in the way some browsers handle eval calls.
How to make a protected member in JavaScript: put an underscore at the start of the name.
Seriously, you're not going to have security boundaries within a JS script that would make real proper protection necessary. Access levels are a trad-OO coder's obsession that make no sense in the context of web scripting. Even if you made real private/protected variables it still wouldn't get you the full encapsulation an effective security boundary would require. JavaScript's ability to fiddle with the prototypes of built-in types your methods will be using gives an attacker the ability to sabotage the methods.
So don't bother try. Just do like the Pythoners do: flag the method as something outsiders shouldn't be calling, and be done with it. If someone uses your code and relies on a member with _ at the start of the name, that's their problem and they have no-one to blame but themselves when their script breaks. Meanwhile you'll make the development and debugging stages easier for yourself by not having strict private and protected members.
Then you can choose per-instance-members (for callback binding convenience) or prototyped members (for efficiency), whether or not you intend them to be private, and you won't trip yourself up on the inconsistency.
http://www.crockford.com/javascript/private.html
Explains it all...

Categories

Resources