Is this is a valid pattern and what is it called? - javascript

I find myself writing the following JavaScript more and more and I would like to know if this is a common pattern and if so, what is it called?
Part of the code and pattern:
var fruits = ["pear", "apple", "banana"];
var getNextFruit = function() {
var _index = 0,
_numberOfFruits = fruits.length;
getNextFruit = function() {
render(fruits[_index]);
_index = (_index + 1) % _numberOfFruits;
}
getNextFruit();
};
I have a function which takes no parameters, inside the function I redefine the function and immediately call it. In a functional language this might be a function being returned, JavaScript just makes it easier because you can reuse the name of the function. Thus you are able to extend the functionality without having to change your implementation.
I can also imagine this pattern to be very useful for memoization where your "cache" is the state we wrap around.
I even sometimes implement this with a get or a set method on the function where I can get the state if it's meaningful. The added fiddle shows an example of this.
Because this is a primarily JavaScript oriented question: The obligatory fiddle

I have a function which takes no parameters, inside the function I redefine the function and immediately call it.
Is this is a valid pattern and what is it called?
A function redefining itself is usually an antipattern, as it complicates stuff a lot. Yes, it sometimes can be more efficient to swap out the whole function than to put an if (alreadyInitialised) condition inside the function, but it's very rarely worth it. When you need to optimise performance, you can try and benchmark both approaches, but otherwise the advice is to keep it as simple as you can.
The pattern "initialises itself on the first call" is known as laziness for pure computations (in functional programming) and as a singleton for objects (in OOP).
However, most of the time there's no reason to defer the initialisation of the object/function/module whatever until it is used for the first time. The ressources taken for it (both time and memory) are insignificant, especially when you are sure that you will need it in your program at least once. For that, use an IIFE in JavaScript, which is also known as the module pattern when creating an object.

Creating a function via a closure is a pretty common pattern in JavaScript. I would personally do that differently:
var fruits = ["pear", "apple", "banana"];
var getNextFruit = function(fruits) {
var index = 0,
numberOfFruits = fruits.length;
function getNextFruit() {
render(fruits[_index]);
index = (_index + 1) % numberOfFruits;
}
return getNextFruit;
}(fruits);
There's no good reason (in my opinion) to clutter up the variable names with leading underscores because they're private to the closure anyway. The above also does not couple the workings of the closure with the external variable name. My version can be made a reusable service:
function fruitGetter(fruits) {
var index = 0, numberOfFruits = fruits.length;
function getNextFruit() {
render(fruits[_index]);
index = (_index + 1) % numberOfFruits;
}
return getNextFruit;
}
// ...
var getNextFruit = fruitGetter(someFruits);
var otherFruits = fruitGetter(["kumquat", "lychee", "mango"]);

Related

Efficiency of Javascript functions

Q1. I would like to confirm whether Version 1 of below code is more efficient than Version 2? I'd like to know for future reference so I will be writing codes according to the style of either V1 or V2.
Q2. How does one measure efficiency of the code? (Doesn't have to be in depth, I just want to have a rough idea)
Version 1:
function average(array) {
return array.reduce(function(a,b) { return a + b; }) / array.length;
}
Version 2:
function average(array) {
function plus(a,b) { return a + b; }
return array.reduce(plus) / array.length;
}
Edit: assuming that at a later stage I would be writing much more complex code and I would like to get into the habit of writing efficient code now. I know that for simple one-liners there's no explicit difference.
These functions are equally efficient from a big-O perspective. The reason they are the same, is that they both pass a function into reduce() (the way in which the function is declared is different, but it's the same underlying structure and thus the same efficiency). The functions are otherwise the same. If I were you, I'd opt for the second case as it is probably easier to maintain.
If you want, you can use a speed test, but honestly it's a waste of your time as these two approaches are identical.
With a sequential loop, it's far faster:
http://jsperf.com/anonymous-vs-named-function-passing/2
function average3(array) {
var sum =0;
for( var i=0, len=array.length; i< len; i++ )
sum+=array[i];
return sum/array.length;
}
You will have the same result. Or difference will be negligible. Depends on JS engine and how good its optimizer is.
As others suggested you can use jsperf.com for speed tests.
But if you really care about performance then check third case here
http://jsperf.com/anonymous-vs-named-function-passing/3
They are the same... but you could optimize by avoiding to create a new closure of the sum function.
function sum(a,b){
return a+b;
}
function average(array){
return array.reduce(sum) / array.length;
}
This way sum won't hold a reference to array in its context; and a new instance of sum with the context won't be necessary. Remember that a closure will hold a reference of the arguments of the function that contains it even if you don't use those arguments.
This means that a new function sum won't be instantiated every time that you call average.

Is it possible to 'import' part of a namespace (a module) into the current scope?

I have one module called functionalUtilities which contains a number of utility functions. An abbreviated version looks something like this:
MYAPP.functionalUtilities = (function() {
function map(func, array) {
var len = array.length;
var result = new Array(len);
for (var i = 0; i < len; i++)
result[i] = func(array[i]);
return result;
}
return {
map:map,
};
})();
I then have a second module which contains core code:
MYAPP.main = (function() {
//Dependencies
var f = MYAPP.functiionalUtilities;
//Do stuff using dependencies
f.map(...)
})()
It seems messy and annoying having to remember to type f.map each time I want to use map. Of course, in the dependencies, I could go though each of my functionalUtilities typing:
var map = f.map,
forEach = f.forEach,
etc.
but I wondered whether there is a better way of doing this? A lot of articles on namespacing that I've read mention aliasing, but don't suggest a way to sort of 'import all of the contents of an object into scope'.
Thanks very much for any help,
Robin
[edit] Just to clarify, I would like to use my functional utilities (map etc) within MYAPP.main without having to preface them every time with f.
This is possible by going through each function in MYAPP.functionalUtilities and assigning to a locally scoped variable within MYAPP.main. But the amount of code this requires doesn't justify the benefit, and it's not a general solution.
As I said in the comment. There is no real way of automatically defining local variables out of object properties. The only thing that comes to my mind is using eval:
for (var i in MYAPP.functiionalUtilities) {
eval("var " + i + " = MYAPP.functiionalUtilities[i];");
}
But I wouldn't use this method, since you could have object properties with strings as keys like this:
var obj = {
"my prop": 1
};
"my prop" might be a valid key for an object property but it's not a valid identifier. So I suggest to just write f.prop or define your local variables manually with var prop = f.prop;
EDIT
As Felix Kling mentioned in the comment section, there is in fact another way of achieving this, using the with statement, which I don't really know much about except for that it is deprectated.
Here's a late answer - I feel like adding to basilikum's answer.
1) The with keyword could be useful here!
with(MYAPP.functiionalUtilities) {
map(console.log, [ 'this', 'sorta', 'works', 'quite', 'nicely!' ]);
// Directly reference any properties within MYAPP.functiionalUtilities here!!
};
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with
The with keyword is, in some ways, intended for exactly this situation. It should, of course, be noted that the mozilla developer link discourages use of with, and with is also forbidden in strict mode. Another issue is that the with statement causes its parameter to become the head of the scope chain, which means that it will always be checked first for all identifiers for all statements within the with block. This could be a performance hit.
2) An improvement to basilikum's answer
While a function call cannot add items to its parent-frame's scope, there is a way to avoid typing out a for-loop each time you wish to add a list of items to a namespace.
// First, define a multi-use function we can use each time
// This function returns a string that can be eval'd to import all properties.
var import = function(module) {
var statements = [];
for (var k in module) statements.push('var ' + i + ' = module["' + i + '"]');
return statements.join(';');
};
// Now, each time a module needs to be imported, just eval the result of import
eval(import(MYAPP.functiionalUtilities));
map(console.log, [ 'this', 'works!' ]);
The idea here is to replace the need to write a for-loop with something like eval(import(MYAPP.functiionalUtilities));.
The danger here, as basilikum has stated, is that module properties need to be valid identifier names.

getting the name of a variable through an anonymous function

Is it possible to find the name of an anonymous function?
e.g. trying to find a way to alert either anonyFu or findMe in this code http://jsfiddle.net/L5F5N/1/
function namedFu(){
alert(arguments.callee);
alert(arguments.callee.name);
alert(arguments.callee.caller);
alert(arguments.caller);
alert(arguments.name);
}
var anonyFu = function() {
alert(arguments.callee);
alert(arguments.callee.name);
alert(arguments.callee.caller);
alert(arguments.caller);
alert(arguments.name);
}
var findMe= function(){
namedFu();
anonyFu();
}
findMe();
This is for some internal testing, so it doesn't need to be cross-browser. In fact, I'd be happy even if I had to install a plugin.
You can identify any property of a function from inside it, programmatically, even an unnamed anonymous function, by using arguments.callee. So you can identify the function with this simple trick:
Whenever you're making a function, assign it some property that you can use to identify it later.
For example, always make a property called id:
var fubar = function() {
this.id = "fubar";
//the stuff the function normally does, here
console.log(arguments.callee.id);
}
arguments.callee is the function, itself, so any property of that function can be accessed like id above, even one you assign yourself.
Callee is officially deprecated, but still works in almost all browsers, and there are certain circumstances in which there is still no substitute. You just can't use it in "strict mode".
You can alternatively, of course, name the anonymous function, like:
var fubar = function foobar() {
//the stuff the function normally does, here
console.log(arguments.callee.name);
}
But that's less elegant, obviously, since you can't (in this case) name it fubar in both spots; I had to make the actual name foobar.
If all of your functions have comments describing them, you can even grab that, like this:
var fubar = function() {
/*
fubar is effed up beyond all recognition
this returns some value or other that is described here
*/
//the stuff the function normally does, here
console.log(arguments.callee.toString().substr(0, 128);
}
Note that you can also use argument.callee.caller to access the function that called the current function. This lets you access the name (or properties, like id or the comment in the text) of the function from outside of it.
The reason you would do this is that you want to find out what called the function in question. This is a likely reason for you to be wanting to find this info programmatically, in the first place.
So if one of the fubar() examples above called this following function:
var kludge = function() {
console.log(arguments.callee.caller.id); // return "fubar" with the first version above
console.log(arguments.callee.caller.name); // return "foobar" in the second version above
console.log(arguments.callee.caller.toString().substr(0, 128);
/* that last one would return the first 128 characters in the third example,
which would happen to include the name in the comment.
Obviously, this is to be used only in a desperate case,
as it doesn't give you a concise value you can count on using)
*/
}
Doubt it's possible the way you've got it. For starters, if you added a line
var referenceFu = anonyFu;
which of those names would you expect to be able to log? They're both just references.
However – assuming you have the ability to change the code – this is valid javascript:
var anonyFu = function notActuallyAnonymous() {
console.log(arguments.callee.name);
}
which would log "notActuallyAnonymous". So you could just add names to all the anonymous functions you're interested in checking, without breaking your code.
Not sure that's helpful, but it's all I got.
I will add that if you know in which object that function is then you can add code - to that object or generally to objects prototype - that will get a key name basing on value.
Object.prototype.getKeyByValue = function( value ) {
for( var prop in this ) {
if( this.hasOwnProperty( prop ) ) {
if( this[ prop ] === value )
return prop;
}
}
}
And then you can use
THAT.getKeyByValue(arguments.callee.caller);
Used this approach once for debugging with performance testing involved in project where most of functions are in one object.
Didn't want to name all functions nor double names in code by any other mean, needed to calculate time of each function running - so did this plus pushing times on stack on function start and popping on end.
Why? To add very little code to each function and same for each of them to make measurements and calls list on console. It's temporary ofc.
THAT._TT = [];
THAT._TS = function () {
THAT._TT.push(performance.now());
}
THAT._TE = function () {
var tt = performance.now() - THAT._TT.pop();
var txt = THAT.getKeyByValue(arguments.callee.caller);
console.log('['+tt+'] -> '+txt);
};
THAT.some_function = function (x,y,z) {
THAT._TS();
// ... normal function job
THAT._TE();
}
THAT.some_other_function = function (a,b,c) {
THAT._TS();
// ... normal function job
THAT._TE();
}
Not very useful but maybe it will help someone with similar problem in similar circumstances.
arguments.callee it's deprecated, as MDN states:
You should avoid using arguments.callee() and just give every function
(expression) a name.
In other words:
[1,2,3].forEach(function foo() {
// you can call `foo` here for recursion
})
If what you want is to have a name for an anonymous function assigned to a variable, let's say you're debugging your code and you want to track the name of this function, then you can just name it twice, this is a common pattern:
var foo = function foo() { ... }
Except the evaling case specified in the MDN docs, I can't think of any other case where you'd want to use arguments.callee.
No. By definition, an anonymous function has no name. Yet, if you wanted to ask for function expressions: Yes, you can name them.
And no, it is not possible to get the name of a variable (which references the function) during runtime.

Why can't I assign for loop to a variable?

So I am just wondering why the following code dosen't work. I am looking for a similar strategy to put the for loop in a variable.
var whatever = for (i=1;i<6;i++) {
console.log(i)
};
Thanks!
Because a for loop is a statement and in JavaScript statements don't have values. It's simply not something provided for in the syntax and semantics of the language.
In some languages, every statement is treated as an expression (Erlang for example). In others, that's not the case. JavaScript is in the latter category.
It's kind-of like asking why horses have long stringy tails and no wings.
edit — look into things like the Underscore library or the "modern" add-ons to the Array prototype for "map" and "reduce" and "forEach" functionality. Those allow iterative operations in an expression evaluation context (at a cost, of course).
I suppose what you look for is function:
var whatever = function(min, max) {
for (var i = min; i < max; ++i) {
console.log(i);
}
}
... and later ...
whatever(1, 6);
This approach allows you to encapsulate the loop (or any other code, even declaring another functions) within a variable.
Your issue is that for loops do not return values. You could construct an array with enough elements to hold all the iterations of your loop, then assign to it within the loop:
arry[j++] = i;
You can do this, but it seems that you might want to check out anonymous functions. With an anonymous function you could do this:
var whatever = function(){
for (var i=1;i<6;i++) {
console.log(i);
}
};
and then
whatever(); //runs console.log(i) i times.

Javascript "Variable Variables": how to assign variable based on another variable?

I have a set of global counter variables in Javascript:
var counter_0 = 0;
var counter_1 = 0;
var counter_2 = 0;
etc
I then have a Javascript function that accepts an 'index' number that maps to those global counters. Inside this function, I need to read and write to those global counters using the 'index' value passed to the function.
Example of how I'd like it to work, but of course doesn't work at all:
function process(index) {
// do some processing
// if 'index' == 0, then this would be incrementing the counter_0 global variable
++counter_+index;
if (counter_+index == 13)
{
// do other stuff
}
}
I hope what I'm trying to accomplish is clear. If not I'll try to clarify. Thanks.
EDIT Clarification:
I'm not trying to increment the name of the counter, but rather the value the counter contains.
Looks like an array to me, or am I missing something?
var counters = [0,0,0];
function process(index) {
++counters[index];
/* or ++counters[index]+index, not sure what you want to do */
if (counters[index] === 13) {
/* do stuff */
}
}
function process(index) {
// do some processing
var counter;
eval('counter = ++counter_'+index);
if (counter == 13)
{
// do other stuff
}
}
Make sure that index really is an integer, otherwise mayhem could ensue.
Edit: Others have pointed out that you should use an array if you can. But if you are stuck with the named global variables then the above approach will work.
Edit: bobince points out that you can use the window object to access globals by name, and so deserves any credit for the following:
function process(index) {
// do some processing
var counter = ++window['counter_' + index];
if (counter == 13)
{
// do other stuff
}
}
Other answers have said "don't use eval()", but not why. Here's an explanation from MDC:
Don't use eval!
eval() is a dangerous function, which
executes the code it's passed with the
privileges of the caller. If you run
eval() with a string that could be
affected by a malicious party, you may
end up running malicious code on the
user's machine with the permissions of
your webpage / extension.
There are safe alternatives to eval()
for common use-cases.
The eval() javascript function will allow you to accomplish this. However it's generally frowned upon. Your question didn't explicitly exclude arrays. Arrays would definitely be more appropriate for the pattern you've described.

Categories