What would be more efficient in terms of computer resources. Putting the event handler inside of a loop like this:
$('ul li').each(function()
{
$(this).mouseover(function()
{
// code to do something
});
Or having the function outside of the loop and creating a call to it inside the loop like this:
$('ul li').each(function()
{
$(this).mouseover(function()
{
doStuff($(this));
});
function doStuff(liElem)
{
// code to do something
}
It seems like to me that the second option would be easier on the computer because the code to do something wouldn't be repeated each time the loop iterates. Does the code of the event handler get created in the computer's memory every time through the loop, or is it just created once? Any thoughts?
There can be various optimizations possible but keeping it specific to the approach you have asked for,
please find the answer as inline comments in the code below
First approach:
$('ul li').each(function()
{
// Maybe you might like to declare some variables here
$(this).mouseover(function()
{
// code to do something
// Maybe you might like to use the variables declared in above function
// Disadvantage over other approach
// The code written here will need to store the context information of the outer function and global context
// Advantage over other approach
// You can directly access the variables declared in the above function
});
}
Or having the function outside of the loop and creating a call to it inside the loop like this:
Second approach:
$('ul li').each(function()
{
// Maybe you might like to declare some variables here
$(this).mouseover(function()
{
doStuff($(this));
});
});
function doStuff(liElem)
{
// code to do something
// Advantage over other approach
// The code written here will need to store the context information only for the global context
// Disadvantage over other approach
// You cannot directly access the variables declared in the outer function as you can in the other approach,
// you will need to pass them to the doStuff function to access here
}
Related
I've been trying to make an object method an iife, but i've had no luck at all. Is it possible? We are storing all of our functions as methods in an attempt to keep them organised.
I have chosen ONE object & one method to illustrate what I am trying to do, though we have many more.
I'd like to IIFe-fy them because as soon as they initially fire, they have done their job and aren't needed again, with that in mind along with how many methods we will have, to me it makes to iife-fy them.
My code is:
let trans = {
bind_toggle: function(){
if ($('.tw-o').length != 0) {
// window open, add toggle
$('.tw-h').click(function(e){
$('.tw-b').toggle(599);
});
}
}
}
I'd like trans.bind_toggle to be invoked without having to call it myself... an IIFE, but i've not been able to pull it off. I've tried:
let trans = {
bind_toggle: (function(){
if ($('.tw-o').length != 0) {
// window open, add toggle
$('.tw-h').click(function(e){
$('.tw-b').toggle(599);
})();
}
}
}
The above returns
Uncaught TypeError: trans.bind_toggle is not a function
Is it possible to use an IIFE in an object? if so, how would I do it?
Thank you :)
Instead storing one-timer-functions in an object, I'd suggest you to wrap all the code in an IIFE, and then declaring the one-timers in the scope of that function, or make them IIFEs like in the example below. That way they will be decently garbage collected after the IIFE has run. Something like this:
(function () {
(function () {
// Logig for bind_toggle
}());
// All the rest of your code
}());
Having all the code in an IIFE you can avoid to declare most of global variables too. If a global is really needed, you can define it as a property of window, like window.someGlobal = 1.
I am studying a JavaScript file and saw in it that some of the methods are wrapped inside a jQuery function. Can Anyone help me how to invoke the following method? And may I know what is the advantage or why the method is wrapped in a function? Below is my sample JavaScript code.
JQuery/JavaScript
$(document).ready(function () {
//How to invoke "testMethod" method?
$(function () {
function testMethod() {
alert("this is a test method");
}
});
});
As you've declared it, testMethod() is a local function and is only available inside the function scope in which it is declared. If you want it to be callable outside that scope, you will need to define it differently so that it is available at a broader scope.
One way of doing that is to make it a global function:
$(document).ready(function () {
//How to invoke "testMethod" method?
$(function () {
window.testMethod = function() {
alert("this is a test method");
}
});
});
testMethod(); // available globally now
It could also be attached to a global namespace or it could be defined at a higher scope where it would also solve your problem. Without specifics on your situation, we can't suggest which one would be best, but the main thing you need to do is to change how the function is declared so it is available in the scope in which you want to call it from.
P.S. Why do you have one document ready function nested inside another? That provides no extra functionality and adds unnecessary complexity. Also, there's really no reason to define testMethod() inside your document ready handlers if you want it available globally.
Before anything else:
$(document).ready(function(){...});
//is the same as
$(function(){...}}
As for your question, here's are potential ways to do it:
If that function is some utility function that everyone uses, then have it available to all in some namespace, like in this one called Utility:
//Utility module
(function(ns){
//declaring someFunction in the Utility namespace
//it's available outside the ready handler, but lives in a namespace
ns.someFunction = function(){...}
}(this.Utility = this.Utility || {}));
$(function(){
//here in the ready handler, we use it
Utility.someFunction();
});
If they all live in the ready handler, and want it to be used by all code in the handler, have it declared in the outermost in the handler so all nested scopes see it.
$(function(){
//declare it in the outermost in the ready handler
function someFunction(){...}
//so we can use it even in the deepest nesting
function nestedSomeFunction(){
someFunction();
}
someElement.on('click',function(){
$.get('example.com',function(){
someFunction();
});
});
nestedSomeFunction();
someFunction();
});
Your call needs to be within the $(function.
It's all about scope and you need to break the testMethod out of the $(function.
Can you perhaps further explain your requirement so that we can maybe help a little better?
Into ready event:
$(document).ready(function () {
//How to invoke "testMethod" method?
var testMethod = function () {
alert("this is a test method");
}
// V0.1
testMethod();
// V0.2
$('#some_id').click(testMethod);
});
In other part:
myObj = {testMethod: null};
$(document).ready(function () {
//How to invoke "testMethod" method?
myObj.testMethod = function () {
alert("this is a test method");
}
});
// Something else
if( myObj.testMethod ) myObj.testMethod();
I need to execute a single function on a set of adjacent DIVS on my page. I thought it would work best like this:
function namedFunction(){
setTimeout(3000);
//do animations and such
$(this).next().call(namedFunction);
}
$("#firstdiv").call(namedFunction());
but I can't find a way to arbitrarily execute a function in a set scope (the firstdiv object), and moreover I'm not even sure if the scope will be passed correctly. Is there a way to do this, or a better way to do this?
I guess you want this:
function namedFunction () {
this.animate({ ... }, function () {
namedFunction.call( $( this ).next() );
});
}
and then:
namedFunction.call( $('#firstdiv') );
The setTimeout() function doesn't pause the current execution, it queues a future execution of a function that you supply. To do something when the page loads use a document ready handler.
I think you want something like this:
$(document).ready(function() {
var $divs = $("div.commonClass"),
i = 0;
function processNextDiv() {
namedFunction($divs.eq(i));
i = (i + 1) % $divs.length;
setTimeout(processNextDiv, 3000);
}
processNextDiv();
});
This first selects all the divs (I'd suggest doing so by giving them a common class, but you can do that any way you like), then sets up a timeout based loop that calls namedFunction() passing it the current div to be processed. So then you could have:
function namedFunction($div) {
$div.animate(...); // process current div
}
Or you could put the animation or other div processing code directly in that processNextDiv() function, depending on whether you want to be able to call namedFunction() from other places.
Demo: http://jsfiddle.net/hWLTb/
Maybe this?
$("#firstdiv").nextAll("div").andSelf().each(function(){
// this = DIV
});
I have multiple document.ready functions on a page and I want a function to be called when all my document.ready functions have been executed. I simply want the function to be called
at the very end, after all other document.ready functions have executed.
An example of this could be that each document.ready function increments a global variable when it has been executed, and the last function needs to check the value of that variable at the very end.
Any ideas ?
This will be enough:
$(function () {
window.setTimeout(function () {
// your stuff here
}, 0);
});
This postpones the execution of your function after all other in the document ready queue are executed.
First idea (for small apps): Tidy up
You can just put everything in one $().ready() call. It might nieed refactoring, but it's the right thing to do in most cases.
Second idea: A Mediator [pattern]
Create a mediator class that will register functions and call its register() instead of $().ready(). When all functions are registered You just loop over the collection and run them in the single and only $().ready() and You have a point in code that is just after all is executed.
I am currently developing a kind of a framework for jquery applications that has a mediator. I might stick together a small version including the mediator if You're interested.
Why not just calling it after all the others ?
$(function(){
func1();
...
funcN();
functionThatNeedsToBeCalledAfter();
});
Of course you will have to cleanup your code to have only 1 place where the document ready function is used... but then your code would be more readable so it's worth it.
little hacky but might work, create a variable inside jquery scope like that
$.imDone = false
then create a function with setTimeout called after short time to lookup for the variable ser to true
var theLastFunctionToCall = function(){
alert('I m the last being called!')
}
var trigger = function(){
$.imDone?theLastFunctionToCall():window.setTimeout(trigger,10);
}
trigger();
I only recommend this when u have different $(document).ready in different big js files, but if you can refactor i sincerelly recommend an optimal solution.
I have a 2000 line jquery file, I just broke up the file into smaller ones, If I have a function in the first file, that file # 2 is referring to, it's coming up undefined.
Every file is is wrapped in a jquery ready function, What's the best way to do this?
If the function in question is declared within the scope of the ready handler, it won't be accessible to any other code, including other ready handlers.
What you need to do is define the function in the global scope:
function foo()
{
alert('foo');
}
$(document).ready(function()
{
foo();
});
P.S. A more concise way of adding a ready handler is this:
$(function()
{
foo();
});
Edit: If the contents of each of your divided ready handlers rely on the previous sections, then you can't split them up, for the reasons outlines above. What would be more sensible would be to factor out the bulk of the logic into independent functions, put these in their own files outside the ready event handler, and then call them from within the handler.
Edit: To further clarify, consider this handler:
$(function()
{
var foo = 'foo';
var bar = 'bar';
alert(foo);
alert(bar);
});
I might then split this up:
$(function()
{
var foo = 'foo';
var bar = 'bar';
});
$(function()
{
alert(foo);
alert(bar);
});
The problem with this is that foo and bar are defined in the first handler, and when they are used in the second handler, they have gone out of scope.
Any continuous flow of logic like this needs to be in the same scope (in this case, the event handler).
Function definition should not be wrapped in another function. Not unless you really want that function definition to be private. And if I understand correctly that's not your intention.
Only wrap function invocation in the jQuery ready function.
If you're worried about your functions clashing with third party function names then namespace them:
var myFunctions = {}
myFunctions.doThis = function () {}
myFunctions.doThat = function () {}
But really, you only need to worry about this if you're creating a mashup or library for others to use. On your own site YOU have control of what gets included in javascript.
Actually, for performance reasons, it may be better to keep it in one file; multiple requests actually can take up more bandwidth... but as separate files, you would need to order them in a particular order so that there is a logical sequence. Instead of having everything in a document.ready, have each script define a method, that the page will execute within its own document.ready handler, so that you can maintain that order.
Most likely the reason it's coming up undefined is because when you have separate ready calls, the scope of the code inside those calls is different.
I would reorganize my code. Any shared functions can be attached to the jQuery object directly, using $.extend. This is what we do for our application and it works well.
See this question. Hope it helps.
Everyfile shouldnt have a ready function. Only one file should have the ready function and that should be the last file.
"wrapped in a jquery ready function" is nothing else than binding stuff to the ready event that is fired when jQuery thinks the DOM is ready.
You should only bind methods that is depending on the DOM to the ready event. It doesnt matter how many binds you make, all of the methods will be executed in the binding order in the end.
Functions provide scope in JavaScript. Your code in the jquery.ready is an anonymous function, so it is unaware of the other scopes. remove the wrappings for those JavaScript functions and declare them as regular functions, a la
$(document).ready(function ()
{
functionFromFile1();
functionFromFile2();
};