My code involves lots of event handlers, which do not require any context (scope) to execute. When I use inline lambda functions in contrast to statically declared (constant) lambda functions, a new event handler is created each time I assign the event handler.
Question: Is it possible to define an inline lambda function, which does not create a new Function object for each time the lambda is passed as a callback. (Given that no unique context scope is required.)
Two examples illustrating the trade-off between notation and memory usage.
1. Inline lambda: (desired notation, unnecesarry memory consumption)
for (const divId of ["div1", "div2", "div3"]) {
documentgetElementById(divId).addEventListener("click", e => console.log(e));
} // Creates a new Function
// object for each loop
// cycle.
Desired notation, but creates a new Function callback (e => console.log(e)) for each divId, despite the callback not depending on any context information (hence being functionally equivalent for each divId). It would be great if there was a way to just pass a pointer to this function.
2. Statically declared lambda: (undesired notation, desired and minimal memory consumption)
const staticLambda = e => console.log(e); // Function object created only once.
for (const divId of ["div1", "div2", "div3"]) {
documentgetElementById(divId).addEventListener("click", staticLambda);
}
Undesired notation (needs the extra constant), but on the up-side only creates the Function callback (staticLambda) once for all three divIds.
Imagine how this would look inside a class method; the lambda function needs to be declared outside of its respective method as a static property of the class, hence destroying the elegance of lambdas (which are so good at keeping the callback code at the location where it is passed).
Note: This is a simplified example. I realize that creating 2 (out of 3) unnecessary callbacks does not affect performance substantially, however, I am interested in properly handling cases with orders of magnitude more callbacks.
You might want to add the event listeners in a function, like this:
function addListeners(ids, listener){
for( const divId of ids){
document.getElementById(divId).addEventListener("click", listener);
}
}
Now you can call your function like this:
addListeners(["div1", "div2", "div3"], e => console.log(e));
While these kinds of optimizations do help in performance (Does use of anonymous functions affect performance?) I don't think it has a very large impact and shouldn't be pursued just for performance reasons, but your case can of course be a valid one.
If you are managing many event listeners you should also take care to remove them when they become unused. Removing an event listener is the easiest if you still have a reference to the original handler around and thus declaring the handler somewhere outside the scope where it is attached.
I would also argue that it is good practice to put 'simple' event handlers in their own functions and keep them in a separate module or file, this allows for easier refactoring. This also solves the performance issue.
Memory usage should not be the reason you choose one form over the other. For two reasons:
The usage is so small as to be almost unmeasurable in most cases.
Javascript interpreters will most likely compile a single function where it can when optimizing bytecode or JIT machine code.
However you should choose either form due to their properties:
Declare implicit function when you have more than one place using the same logic. Always look for opportunities to refactor code especially an easy refactor as naming a function. It reduces future workload when fixing bugs.
When you need to instantiate a new closure each time you call your function then use an IIFE (inline). Modern javascript may compile it to a single function but they will create a new closure each time the function is "redeclared".
Related
I recently joined a large software developing project which uses mainly JavaScript and a particular question has been on my mind since day one. I know this issue has been here on SO before, but I have never seen the core question being properly answered. So here I ask it again:
Are there any benefits in JavaScript in using function expressions rather than function declarations?
In other words, is this:
var myFunction = function () {
// Nice code.
}
in any way better than this:
function myFunction () {
// Nice code.
}
As I see it, function expressions only introduce negative aspects on several levels to the code base. Here I list a few.
Function expression as the one above, suddenly forces you to be careful with forward references, as the anonymous function object that the myFunction variable refers to, does not exist until the variable expression actually executes. This is never a problem if you use function declarations.
Apart from generating twice as many objects as in the case with function declarations, this usage introduces a very bad programming habit, which is that developers tend to declare their functions only when they feel they need them. The result is code that mixes object declarations, function expressions and logic in something that obscures the core logic of a piece of code.
As a side effect of 2), code becomes much harder to read. If you would use proper function declarations and only var declarations for objects that actually will be variable in the code, it becomes far easier to scan the indentation line of code segment and quickly find the objects and the functions. When everything is declared as "var", you are suddenly forced to read much more carefully to find this piece of information.
As yet another nasty side effect of 2), as users get into the bad habit of only declaring their functions when they feel they need them, function expressions start showing up inside event handlers and loops, effectively creating a new copy of the function object either each time an event handler is called or for each turn in the loop. Needless to say, this is bad! Here is an example to show what I mean:
var myList = ['A', 'B', 'C'];
myList.forEach(function (element) {
// This is the problem I see.
var myInnerFunction = function () {
// Code that does something with element.
};
};
So to sum up, at least in my view, the only situation in which it is fair to use something like:
var myFunction = function () {
// Nice code.
}
is when your logic intends to change the myFunction reference to point at different functions during execution. In that situation myFunction (the variable) is something that is variable in the code, hence you are properly informing a different programmer of your intents, rather than confusing him/her.
With this background in mind, I ask my question again. Have I missed something central about function expressions (in the context described above) in which they provide any benefit over function declarations?
The former seems to be much more "hip" in JavaScript, and I don't understand why.
Edit: in response to this question possibly being a duplicate, my interest is why, not how. And another question asking only about "closures" in the title wouldn't catch the eye of the person who hasn't made the link between this and closures yet.
tl;dr: Because many functions are actually not reused.
I think you answered your own question:
... instead of just the function name which can be reused?
Many of these are "one-off" cases. The line of code is executed once and the passed function doesn't have to be reused.
For example, if I want to bind an event handler to a body and I don't intend to reuse the event handler anywhere, why should I write
function bodyEventHandler() {}
document.body.addEventListener('click', bodyEventHandler);
and unnecessarily pollute the current scope with bodyEventHandler?
document.body.addEventListener('click', function() {...});
has the same effect, doesn't pollute the scope and keeps the function definition where it is used.
JavaScript is very much event-driven, and most event handlers are actually not going to be reused anywhere else.
Keeping the function definition where the function is used is also a common reason IMO. Some functions are either very simple, but it may not be easy to give them descriptive names.
E.g. if you are not familiar with the term "pluck", would you understand what
var names = users.map(pluck('name'));
really does? Maybe you can infer it from the other variables names.
However,
var names = users.map(function(user) { return user.name; });
makes it immediately clear.
In fact, you will see these even more often, now that ECMAScript 6 introduces arrow functions, which are like lambda functions in other languages:
var names = users.map(user => user.name);
I also think you have a misconception of what exactly happens under the hood when you pass a function:
... pass an entire function definition as an argument instead of just the function name ...
foo(bar) does not pass the name "bar" to foo. It passes the function object that is referenced by the variable bar. That is no different from foo(function() { ... }). The only difference is that we are not (temporarily) storing the function in a variable.
This is subjective (opinion based) - but only to a degree, don't rush voting to close. Causing some arguments at work as everyone has a different opinion and people are trying to enforce a single way of doing it.
Simple context: when you have the option to save a reference in your closure to the instance or to use a polyfilled Function.prototype.bind, what possible disadvantages do you see to either approach?
To illustrate possible usecases, I just made up some class methods.
Pattern one, saved ref:
obj.prototype.addEvents = function(){
var self = this;
// reference can be local also - for unbinding.
this.onElementClick = function(){
self.emit('clicked');
self.element.off('click', self.onElementClick);
};
this.element.on('click', this.onElementClick);
};
Pattern two, a simple fn.bind:
obj.prototype.addEvents = function(){
// saved reference needs to be bound to this to be unbound
// once again, this can be a local var also.
this.onElementClick = function(){
this.emit('clicked');
this.element.off('click', this.onElementClick);
}.bind(this);
this.element.on('click', this.onElementClick);
};
Pattern two and a half, proto method to event:
obj.prototype.addEvents = function(){
// delegate event to a class method elsewhere
this.element.on('click', this.onElementClick.bind(this));
};
obj.prototype.onElementClick = function(){
this.emit('clicked');
this.element.off('click', this.onElementClick); // not matching due to memoized bound
};
Personally, I am of the opinion that there isn't a single correct way of doing this and should judge on a per-case basis. I quite like the saved reference pattern where possible. I am being told off.
Question recap:
Are there any GC issues to be considered / be mindful of?
Are there any other obvious downsides or pitfalls you can think of on either method?
Polyfill performance or event native .bind vs a saved ref?
My personal preference is to use the saved reference method. Reasoning about the value of this can be very hard sometimes because of how JavaScript treats this.
The bind is nice but if you miss the .bind(this) it looks like a bug.
The latter exposes too much; every time you need a callback you'd need to expose another helper in your API.
There are many ways to use prototyping. I think the most important thing is to pick one and stick to it.
Are there any GC issues to be considered / be mindful of?
Older engines don't infer what variables are still used from the closure and do persist the whole scope. Using bind does make it easy because the context is explicitly passed and the un-collected scope does not contain additional variables.
However, this doesn't make a difference if you're using a function expression anyway (as in patterns #1 and #2).
Are there any other obvious downsides or pitfalls you can think of on either method?
Saving reference:
needs an additional line for declaring the variable, sometimes even a whole new scope (IEFE)
Code can't be easily moved because you need to rename your variable
Using bind:
Easily overlooked on the end of a function expression (just like the invocation of an IEFE), it's not clear what this refers to when reading from top to bottom
Easily forgotten
I personally tend to use bind because of its conciseness, but only with functions (methods) declared elsewhere.
Polyfill performance or event native .bind vs a saved ref?
You don't care.
In your example, you actually don't need that reference to the bound function and the off method. jQuery can take care of that itself, you can use the one method for binding fire-once listeners. Then your code can be shortened to
obj.prototype.addEvents = function(){
this.element.one('click', this.emit.bind(this, 'clicked'));
};
I've been reading about memory leakages lately and haven't yet wrapped my head around all of it and have some questions regarding my own style of writing. Specifically, I'm not really sure if the way I handle events might be a source of leaking. Consider the following code
function Wrapper(text) {
this.text = text;
this.bindHandlers();
};
Wrapper.prototype.onClick = function (e) {
alert(this.text);
};
Wrapper.prototype.bindHandlers = function () {
var t = this, div = $('<div>' + this.text + '</div>');
var reallyHugeArray = [1,2,3...]; // an array of 100000 elements for example
div.click(function (e) {
// all variables of the parent function are in scope for this function, including reallyHugeArray
t.onClick(e);
});
$(document).append(div);
};
var a = new Wrapper('testString');
// had enough fun with the Wrapper, now let's nullify it
a = null;
As you can see, I like to use an anonymous functions as the event handler so that it would be more convenient to have access to instance specific variables (in this case this.text in the onClick function) and functions. However, if I understood correctly, having an anonymous function inside a function (as is the event handler), which has access to the local scope, disables the garbage collector from removing the local variables, therefore creating a leak.
So my question is whether this method of event handling can create memory leakages and if it does, is there any way to prevent it, but still have a similarily convenient way to access the instance variables and functions?
(Off-topic: a function inside a function inside a function makes Javascript sound like Inception)
In your particular example, the anonymous click handler creates a function closure for the scope above it. That means that the values of t, div and reallyHugeArray are maintained for the life of your anonymous click handler function.
This is not a really a memory "leak", but rather memory "usage". It doesn't get worse and worse over time, it just uses the fixed amount of memory that those local varaibles t, div and reallyHugeArray occupy. This is often an advantage in javascript programming because those variables are available to the inner function. But, as you wondered, it can occasionally cause problems if you expected that memory to be freed.
In the case of references to other things (DOM objects or other JS variables), since these outer variables continue on, everything that they refer to also continues on and cannot be freed by the garbage collector. In general, this is not a big problem. Things that tend to cause problems are things that are done over and over as the web page is used or things that are done in some large loop with lots of iterations. Something only executed once like this just uses a little more memory once and from then on the memory usage of the construct is constant.
If, for some reason, you were binding this event handler over and over again, creating a new function closure every time and never releasing them, then it could be a problem.
I find this construct in Javascript very useful. I don't think of it as something to stay away from, but it is worth understanding in case you have references to really large things that you want to be freed, transient things that should be freed because you don't need them long term or you're doing something over and over again. In that case, you can explicitly set local variables to null if you won't need them in the inner function to kill their references and allow the garbage collector to do it's thing. But, this is not something you generally need to do - just something to be aware of in certain circumstances.
I am trying to organize my JavaScript. What I would like to do is have a class for each PAGE rather then just entering JavaScript straight into a js - is this good practice?
Let me explain: thinking along the lines of is it a good or bad idea on my variable naming. Remember that this a kind of class so I have to create the class but then I must call it (see below). I am using the prototype and constructor pattern.
// THIS FILE WILL BE SAVED as RESERVATIONPAGE
function ReservationPage(){
// Setup click events in this constructor
$('submit-button').bind('click',this.submit_click);
$('clear-button').bind('click',this.clear_click);
// setup other variables
}
ReservationPage.prototype = {
constructor: ReservationPage,
submit_click : function () {
alert(' you just clicked the submit button');
},
clear_click : function () {
alert('button for clearning the form fields!!');
}
};
Then each page will need a standard js file i.e. not a class / object to instantiate their Page js like above, so a kind of entry point - so hence:
// THIS FILE WILL BE SAVED as ReservationLoad - notice the word Load :-) -- don't know if this is good naning convetion, anybody suggest anything different??
var reservationPage = new ReservationPage(); // CREATES NEW INSTANCE OF THE CLASS/OBJECT ..
I don't any other way of doing it; I would really appreciate any input. I will be using jQuery extensively but this shouldn't matter. I need a standard JS file - no objects to instantiate my objects hence I called in load. This in turn instantiates the object and calls the constructor.
The constructor sets up the click events and then calls the methods.
Is this good?
Any idea where I am going wrong?
I really appreciate some input as I am little lost and want to do it right. I am coming from a C# .NET background, and I know js isn't a proper OOP language but I am trying to treat it like this for better structuring.
This way, all my js files are separate from my HTML and my CSS; there are no events entered into the html, they are all entered via code
Look forward to any info
JavaScript is a proper OOP language. It's not class-based like you're used to (it's prototype-based), but it is absolutely object-oriented -- very much so.
You can simulate classes and class-based inheritance in JavaScript (it's that powerful), which can be useful for people like you (and me) with backgrounds in that world. But classes are not the only way to modularize, which is really what you're talking about doing.
The solution presented in your question creates a function backed by an object (the prototype) which you can then use to create another object (the instance) that then does what you want. That fits the class-based mindset (which may be a good enough reason to do it!), and it's what I do for things I may need to create more than one of, but in some sense it may be overkill for this purpose, since you're not going to have multiple instances of your page objects at any given time. It also means that your click handlers won't work as defined in your example code -- when they're called in response to a click, the this value will be wrong, it won't point to your ReservationPage instance. (Functions in JavaScript are just functions, they're not methods; this is defined by how the function is called, not how it's defined. Surprising to people like us, but it turns out that it's incredibly useful.) That can be worked around, of course, but it requires...working around it.
Since you're only going to need one instantiated object for the page, rather than all the hassle of constructor functions and prototypes such, why not just have one object for the page? And you can use a closure (function) to put scope around that object so it can have easily-accessed variables without having to worry about this and without polluting the global namespace. Here's an example of doing that:
// Create a closure (function) to scope our variables, assign its
// return value to a variable for our page
var reservationPage = (function() {
var somePageData; // A private variable for our page
// Our load function; we'll export that below
function onLoad() {
// Hook some elements
$('submit-button').bind('click', submit_click);
$('clear-button').bind('click', clear_click);
// Set up some page data
somePageData = 42;
}
// A private function for handling the click of the submit button
function submit_click() {
alert('You just clicked the submit button; page data is ' + somePageData);
}
// A private function for handling the click of the clear button
function clear_click() {
alert('You just clicked the clear button; page data is ' + somePageData);
}
// Export any functions we may need outside the closure
return {onLoad: onLoad};
})();
$(document).ready(reservationPage.onLoad);
Note that all of the functions have access to the somePageData variable, and to each other, but we didn't have to worry about this. That's because the functions are declared within the scope in which the somePageData is declared, and so they "close over" it (have access to it). That access is "live", it's not a copy or something.
Note that I've wrapped the entire thing in a function. I'm doing that because we want to avoid just dumping everything in the global namespace, because A) it's the Right Thing(tm), and B) you're combining all of your pages into one file you reuse. You could have four or five (or 20) page objects in your combined file, all definining a var with that same name, and they'd be kept distinct because they're declared inside separate functions. Similarly, the functions for the page (onLoad and the like) are scoped to the function. Using a scoping function like this is called the "module pattern."
I also didn't bother to export any more than I had to make public (just the onLoad function). There's no need for our handlers to be available outside the closure.
Another aspect of the above that can be useful: All of the functions we care about have names. Named functions help tools help you, by telling you where an exception occurred, etc. There's a big difference, from a tool's point of view, between an anonymous function assigned to a variable:
var fname = function() { /* ... */ };
...and a named function:
function fname() { /* ... */ };
This is just a side-note, though; you can do that with the code in your question, too:
ReservationPage.prototype = (function(){
function submit_click() {
alert(' you just clicked the submit button');
}
function clear_click() {
alert('button for clearning the form fields!!');
}
return {
constructor: ReservationPage,
submit_click: submit_click,
clear_click: clear_click
};
})();
Now, I wouldn't use the "one object" pattern for anything general purpose that I might want more than one of; that's what classes (or things like classes) are for. Hence the links above to simulating classes and solving the this problem. :-) But for modularizing and organizing the script that's specific to the page, classes may be overkill.