The problem with functional inheritance is that if you want to create many instances then it will be slow because the functions have to be declared every time.
The problem with prototypal inheritance is that there is no way to truly have private variables.
Is it possible to mix these two together and get the best of both worlds? Here is my attempt using both prototypes and the singleton pattern combined:
var Animal = (function () {
var secret = "My Secret";
var _Animal = function (type) {
this.type = type;
}
_Animal.prototype = {
some_property: 123,
getSecret: function () {
return secret;
}
};
return _Animal;
}());
var cat = new Animal("cat");
cat.some_property; // 123
cat.type; // "cat"
cat.getSecret(); // "My Secret"
Is there any drawbacks of using this pattern? Security? Efficiency? Is there a similar pattern out there that already exists?
Your pattern is totally fine.
There are a few things that you'd want to keep in mind, here.
Primarily, the functions and variables which are created in the outermost closure will behave like private static methods/members in other languages (except in how they're actually called, syntactically).
If you use the prototype paradigm, creating private-static methods/members is impossible, of course.
You could further create public-static members/methods by appending them to your inner constructor, before returning it to the outer scope:
var Class = (function () {
var private_static = function () {},
public_static = function () {},
Class = function () {
var private_method = function () { private_static(); };
this.method = function () { private_method(); };
};
Class.static = public_static;
return Class;
}());
Class.static(); // calls `public_static`
var instance = new Class();
instance.method();
// calls instance's `private_method()`, which in turn calls the shared `private_static();`
Keep in mind that if you're intending to use "static" functions this way, that they have absolutely no access to the internal state of an instance, and as such, if you do use them, you'll need to pass them anything they require, and you'll have to collect the return statement (or modify object properties/array elements from inside).
Also, from inside of any instance, given the code above, public_static and Class.static(); are both totally valid ways of calling the public function, because it's not actually a static, but simply a function within a closure, which also happens to have been added as a property of another object which is also within the instance's scope-chain.
As an added bonus:
Even if malicious code DID start attacking your public static methods (Class.static) in hopes of hijacking your internals, any changes to the Class.static property would not affect the enclosed public_static function, so by calling the internal version, your instances would still be hack-safe as far as keeping people out of the private stuff...
If another module was depending on an instance, and that instance's public methods had been tampered with, and the other module just trusted everything it was given... ...well, shame on that module's creator -- but at least your stuff is secure.
Hooray for replicating the functionality of other languages, using little more than closure.
Is it possible to mix functional and prototypical inheritance together and get the best of both worlds?
Yes. And you should do it. Instead of initializing that as {}, you'd use Object.create to inherit from some proto object where all the non-priviliged methods are placed. However, inheriting from such a "class" won't be simple, and you soon end up with code that looks more like the pseudo-classical approach - even if using a factory.
My attempt using both prototypes and the singleton pattern combined. Is there a similar pattern out there that already exists?
OK, but that's something different from the above? Actually, this is known as the "Revealing Prototype Pattern", a combination of the Module Pattern and the Prototype Pattern.
Any drawbacks of using this pattern?
No, it's fine. Only for your example it is a bit unnecessary, and since your secret is kind of a static variable it doesn't make much sense to me accessing it from an instance method. Shorter:
function Animal(type) {
this.type = type;
}
Animal.prototype.some_property = 123;
Animal.getSecret = function() {
return "My Secret";
};
Related
If a constructor and it's prototype are defined in the same module, say AMD module, is it acceptable to make class private fields global for the module to be accessible within prototype instead of defining them with underscore inside a constructor?
So is this better:
define(function (require) {
"use strict";
var steps = 0;
function Constructor(_steps) {
steps = _steps;
}
Constructor.prototype.go = function () {
steps += 1;
};
then this:
define(function (require) {
"use strict";
function Constructor(_steps) {
this._steps = _steps;
}
Constructor.prototype.go = function () {
this._steps += 1;
};
?
TL;DR: doesn't really matter (it's just a minor implementation detail)
Two different solutions. One isn't necessarily "better" than the other, they just have different use cases.
If you're using the constructor/prototype pattern, then it makes sense in an object-oriented sense to set the constructor parameters on the instance itself (using this.<whatever-prop>). When you instead decide to use the constructor only for the sake of its side effects (by setting someModuleVariable based on the parameter passed to the constructor), it can unnecessarily obfuscate the code.
Having a "private" variable that's accessible to the entire module, however, is an extremely common pattern... For example, when using singleton objects, because scoped variables are never destroyed when you leave the execution context of the function, the module can still query that "module-local" variable.
The only thing that rubs me the wrong way is using the constructor only for the sake of its side effects... why would I use a constructor then, when one of the main purposes of a constructor is the implicitly set properties on the instance?
To separate these two ideas, a common pattern is to use an init method inside of the prototype, because that's a good place to harbor all of your desired side effects. For example, one could suggest doing this:
var Module = (function() {
var somethingPrivate;
function SomeObject(someProp) {
// rely on the constructor to set instance properties
this.someProp = someProp;
}
SomeObject.prototype = {
init: function(_somethingPrivate) {
// all of your side effects in here, such as:
somethingPrivate = _somethingPrivate;
}
};
return SomeObject;
}());
var module = new Module('Hello world! I belong to the instance');
module.init('I am a module-specific variable!');
Of course, however, this isn't saying that there aren't circumstances where you might want to rely on a constructor for its side effects. But in the example you gave, it doesn't even look like a constructor is necessary (even though I understand the example is contrived just for the sake of demonstrating the problem).
Where and how you use _ underscores are mostly irrelevant, just as a side note. They're good in some cases, like to differentiate pseudo-private properties from "public" properties, but I think that's more of a convention than a pattern that's been set in stone.
Below I've got a simple little inheritance chain in JavaScript:
var Base =(function(){
function Base(config){
this.name = function(){
return config.name;
}
this.department = function(){
return config.department;
}
}
Base.prototype.calculate = function(){
return this.name().length + this.department().length;
}
return Base;
})();
var base = new Base({
name: 'me',
department: 'this one'
});
console.log(base.calculate());
//inheritance
var Concrete = (function(){
Concrete.prototype = Base.prototype;
function Concrete(config){
Base.apply(this,arguments);
this.number = function(){
return config.number;
}
}
return Concrete;
})();
var concrete = new Concrete({
name: 'concrete',
department: 'the best',
number: 3
});
console.log(concrete.number()); //3
console.log(concrete.name()); //concrete
and it works as expected. I'm curious, though about how correct it would be to place method properties on the prototype of an object. Canonically I know that instance data should go with the instance of the class and the methods the object actually uses should be on the prototype, but what about the situation where the properties themselves are methods (like name and department in Base in this example)? In the interest of keeping things immutable I'd rather not let users change the properties of one of these objects after they've been initialized. In this case does it make any sense to use the prototype instead of the constructor to add functionality to an object?
Or it is only correct to place properties in the constructor so you have access to them when you do something like Base.prototype.whatever?
what about the situation where the properties themselves are methods? In the interest of keeping things immutable I'd rather not let users change the properties of one of these objects after they've been initialized.
I wouldn't call these "properties" any more, but "accessor" or "getter" methods.
In this case does it make any sense to use the prototype instead of the constructor to add functionality to an object?
Yes, if you mean functionality like calculate. If you mean getters like name, department or number you need to place them in the constructor as they need privileged access to the config.
Canonically I know that instance data should go with the instance of the class and the methods the object actually uses should be on the prototype
It's a bit different actually:
Everything instance-specific (data, accessor methods with distinct scopes) needs to go on the instance and is usually set up in the constructor
Everything that is shared amongst all instances (typically methods, but also data in some rare cases) should go on the prototype.
Concrete.prototype = Base.prototype;
No! Use Concrete.prototype = Object.create(Base.prototype); instead.
The heading of your question is a bit misleading.
A direct answer to your heading - Yes, prototype properties are encouraged. They might not make a lot of difference wrt writing the code and the usage of the code, but internally, how JS manages things, like memory, accessing the variables inside closures etc it much better when done via prototype properties.
Now your actual question, is hiding immutable configurations using closures and private scoped variables the only way to do things ?
Right now - I think yes, as ES6 is still not supported completely by every browser yet.
But soon, the support will spread out in all release version of browsers and then you can use this nifty ES6 data type WeakMap . Just like a Map but here the keys are objects. So your Base definition can be written like:
var Base = (function() {
var properties = new WeakMap(); // You have to keep variable private
function Base(config) {
properties.set(this, config);
}
Base.prototype = {
name: function() {
return properties.get(this).name;
},
department: function() {
return properties.get(this).department;
},
calculate: function() {
return this.name().length + this.department().length;
}
};
return Base;
})();
Yes, you still need to keep the variable properties out of reach, so the outer closure. But the number of closures have decreased by 1 in this case.
Similar approach can be for ES6 Symbol but the outer closure will still be required.
What we truly need here are classes which will truly solve the issue, as explained in this very well written blog
I am already familiar with the module pattern where we define a module with private state with the funcitons closure and an exposed set of public methods. However this seems to be closer to a singleton than an object.
However what if i wanted a more object orientated pattern can I use the same structure as the module pattern but don't immediately execute, Something like this:
function MyPseudoClass(constructorArg0, constructorArg1... ) {
var privateVar = "private!!";
var privateComplexVar = constructorArg0;
var privateComplexVar1 = constructorArg1;
return {
publicVar: "public Varaible!",
publicMethod: function() {
//code
return privateVar + 1;
}
};
Now in my code i can create instances of my pseudo class like so:
var instance = MyPseudoClass({p : 2, q : 100},"x")
var anotherInstance = MyPseudoClass({p : 3, q : 230},"y")
As far as i can tell this seems to do what i want but i haven't seen anyone using this online, are there any downsides to this approach that i should be aware of?
You aren't using prototypical inheritance; that is the main difference. Your main drawbacks are:
You cannot use instanceof to ensure that a variable is of some type (so you cannot do myVar instanceof MyPseudoClass. You don't create an instance with this method; you just create an object.
A prototype-based approach might be faster as there is overhead associated with closures. Furthermore, in a prototyped approach, each instance will share can share the same instance of a function (that is assigned to the prototype). But in the closure approach, each "instance" will have its own copy of the function. However, the difference is small (especially in newer browsers).
If you aren't concerned about these drawbacks, you should be ok.
Please help me decide whether I should use a function's prototype object and the "new" keyword or completely stay away from constructor functions.
Situation:
Function called widget() that will be called 10-15 times to initialize each widget on the page. widget() contains quite a few internal methods.
Each time widget() is called, the function needs to return an object that acts as an API to operate on the widget.
Question
1) Do I put all the internal methods inside Widget() under its prototype property? It does not make sense but the main reason for this is to not re-instantiate the internal functions every time widget() is called.
But if I do put the internal functions in prototype, each instantiated w object (w = new Widget();) has access to internal private methods.
2) If I stay away from constructor functions and new keyword and structure my code as down below, how do I fix the performance concern of the internal functions getting re-instantiated every time widget() is called.
function widget()
{
var returnObj = {};
/* Add internal functions but this will be re-instantiated every time */
return returnObj;
}
You have a bit of a tradeoff here. As you seem to already understand, methods you put on the .prototype are publicly available, but that is the most efficient places to put methods as they are automatically added to all new copies of that object in a very efficient manner. When using .prototype for methods, there is only one copy of your methods and a reference to that single copy is automatically added to all new instantiations of that object.
But, javascript doesn't have private methods built-in and the only work-around for that involves not using the .prototype for them or for any methods that need to call the private methods.
This article by Doug Crockford is a pretty good description of how you can create privacy for either data or methods in any object.
In either case, I don't see any reason to avoid using the new keyword to create new objects. You can make either .prototype or private methods work with new.
But, if you want to achieve truly private methods, then you can't use .prototype for either the private methods or any methods that need to access them so you have to decide which is more important to you. There is no single correct answer because your need for privacy is situation-specific.
In my coding, I generally don't enforce privacy and I do use .prototype and new. I designate "non-public" methods on the prototype by starting their name with an underscore. This is a notational convention, not an access enforcement scheme.
In answer to your second question about avoiding the new operator and reinstantiating methods, I'd just ask why you're doing this? What are you gaining? I'm not aware of any downsides to using new. As best I understand your decision about whether to use .prototype vs. manually create/assign methods in your constructor should be about the need for private methods.
FYI, 15 objects is hardly going to create a significant difference in performance either way here. I would evaluate your need for true privacy and make your decision based on that. If you HAVE to enforce privacy, then go with the Crockford method for implementing private methods. If you don't HAVE to have true privacy, then use .prototype. I don't see a reason here to avoid using new in either case.
You can use a metaconstructor* pattern to get around this.
function defineCtor(metaCtor) {
var proto = new metaCtor();
var ctor = proto.hasOwnProperty('constructor') ?
proto.constructor : new Function();
return (ctor.prototype = proto).constructor = ctor;
}
Now you have a function that constructs constructors (or more accurately constructs prototypes and returns constructors).
var Widget = defineCtor(function() {
function doInternalStuff() {
// ...cant see me
}
// this function ends up on the prototype
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
Explanation
defineCtor takes a single anonymous function as a property. It invokes the function with new, creating an object. It assigns the object as the prototype property of a new constructor function (either an empty function, or the generated prototype object's own constructor property), and returns that function.
This provides a closure for your internal functions, addressing your question 1, and sets up the constructor/prototype pair for you, addressing question 2.
Comparison
Compare the defineCtor technique to the following two examples.
This example uses the prototype, and has problem 1: the internal stuff is not encapsulated.
function Widget(options) {
this.options = options;
}
Widget.prototype = {
getFoo: function() {
return doInternalStuff();
}
};
// How to encapsulate this?
function doInternalStuff() { /* ... */ }
This example sets up everything in a constructor, and has problem 2: each time it constructs an object, it instantiates new function objects for each property.
function Widget(options) {
this.options = options;
function doInternalStuff() { /* ... */ }
this.getFoo = function() {
return doInternalStuff();
};
}
This example uses the technique described above to provide encapsulation while still leveraging the prototype:
var Widget = defineCtor(function() {
// ^
// This function runs once, constructing the prototype.
// In here, `this` refers to the prototype.
// The real constructor.
this.constructor = function(options) {
// In function properties, `this` is an object instance
// with the outer `this` in its prototype chain.
this.options = options;
};
function doInternalStuff() { /* ... */ }
this.getFoo = function() { return doInternalStuff(); };
});
// ...
var myWidget = new Widget();
This approach has a few benefits, some more immediately obvious than others.
It provides encapsulation. You could do this by wrapping the first "comparison" example in an immediately invoked function, but this approach may be cleaner and more easily "enforced" in a team setting.
It's extensible. You can give your "metaconstructor" functions their own prototypes, with function properties like "extends", "mixin", etc. Then, inside the body of metaCtor, you can write things like this.extends(BaseWidget). The defineCtor API never needs to change for any of this to happen.
It "tricks" Google Closure Compiler, Eclipse, jsdoc, etc. into thinking you are defining the actual constructor function rather than a "meta function." This can be useful in certain situations (the code is "self-documented" in a way these tools understand).
* As far as I know, the word "metaconstructor" is completely made up.
Just saw some interesting code while doing a typo in coffee-script. I got the following code
var Mamal, mam;
Mamal = (function() {
var __priv_func;
function Mamal() {}
Mamal.prototype.simple_var = 5;
Mamal.prototype.test = function() {
return __priv_func(this);
};
__priv_func = function(instance) {
return alert(instance.simple_var);
};
return Mamal;
})();
mam = new Mamal();
mam.simple_var = 10;
mam.test();
Now I've read alot about the module pattern in javascript and why its a bad thing (takes more memory, longer to create...) but of course the upside is having truly private functions/variables. Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?
One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?
To highlight the points I was making, because clearly there was more to the question than just the title:
Yes a module pattern is a good and commonly used way to create private (er, local) data (functions or whatever), and export some sort of interface. Since a function is the only way to create variable scope, it's the only way to create private functions.
Because the functions will be shared by all objects created from Mamal, they're not useful for a functional inheritance pattern (references to functional inheritance have been removed from the question).
There's no performance improvement over lookups in the prototype chain, because the prototype chain needs to be traversed anyway just to get to your private functions.
To address specific questions points in the updated post:
"Would this be a good way to do private functions?"
Sure, but that's because having a function nested in another is the only way to scope a function.
"Now I've read alot about the module pattern in javascript and why its a bad thing..."
For a one-time use module, I don't see any issue. Also, any data referenced by variables that are no longer needed after the module function exits is free for garbage collection. This wouldn't be the case if they were global, unless you nullified them.
"...of course the upside is having truly private functions/variables..."
Yes, though some would take exception to the use of the word "private". Probably "local" is a better word.
"...this wouldn't work for variables, unless you wanted static private variables..."
Yes, though again some may take exception to the use of the word "static".
"Wouldn't the above code be a good way to create private functions...as the function is only created once in the closure?"
Yes again, nested functions are the only way to make them "private" or rather local.
But yes, as long as the function only ever needs to access the public properties of the objects (which are accessible to any code that can access the object) and not local variables of the constructor, then you should only create those functions once, whether or not you use a module pattern.
"One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"
No, you haven't exported your private functions directly, but rather the only way to call them is by traversing the prototype chain.
But if you ditched the prototype chain, and added functions as properties directly on the objects created, then you'd have some improvement there.
Here's an example:
Mamal = (function() {
var __priv_func;
function Mamal() {
this.test = __priv_func;
}
Mamal.prototype.simple_var = 5;
__priv_func = function() {
return alert( this.simple_var );
};
return Mamal;
})();
Now you've eliminated the prototype chain in the lookup of the test function, and also the wrapped function call, and you're still reusing the __priv_func.
The only thing left that is prototyped is the simple_var, and you could bring that directly onto the object too, but that'll happen anyway when you try to modify its value, so you might as well leave it there.
Original answer:
If you're talking about a module pattern, where you set up a bunch of code in (typically) an IIFE, then export methods that have access to the variables in the anonymous function, then yes, it's a good approach, and is pretty common.
var MyNamespace = (function () {
// do a bunch of stuff to set up functionality
// without pollution global namespace
var _exports = {};
_exports.aFunction = function() { ... };
_exports.anotherFunction = function() { ... };
return _exports;
})();
MyNamespace.aFunction();
But in your example, I don't see and advantage over a typical constructor, unless you decide to use the module pattern as above.
The way it stands right now, the identical functionality can be accomplished like this without any more global pollution, and without the wrapped function:
var Mamal, mam;
Mamal = function() {};
Mamal.prototype.test = function() {
return console.log(this.simple_var);
};
Mamal.prototype.simple_var = 5;
mam = new Mamal();
mam.simple_var = 10;
mam.test();
" Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?"
Given the rewritten code above, the function is still only created once. The prototype object is shared between objects created from the constructor, so it too is only created once.
"One of the upsides of functional inheritance is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"
In your code, the function is called via a function in the prototype chain, so it has that same overhead, plus the overhead of finding the local function in the variable scope and invoking that function as well.
So two lookups and two function invocation instead of one lookup and one invocation.
var Mamal, mam1, mam2;
Mamal = (function() {
//private static method
var __priv_func = function() {
return 1;
};
function Mamal() {
}
Mamal.prototype.get = function() {
return __priv_func();
};
Mamal.prototype.set = function(i) {
__priv_func = function(){
return i;
};
};
return Mamal;
})();
mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); //output 1
mam2.set(2);
console.log(mam1.get()); //output 2
The function __priv_func is not only private, but also static. I think it's a good way to get private function if 'static' does not matter.
Below is a way to get private but not static method. It may take more memory, longer to create.......
var Mamal, mam1, mam2;
function Mamal() {
//private attributes
var __priv_func = function() {
return 1;
};
//privileged methods
this.get = function() {
return __priv_func();
};
this.set = function(i) {
__priv_func = function(){
return i;
};
};
}
mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 1
mam2.set(2);
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 2