Use same variable that is defined in another function - javascript

This may seem simple to some but I am less experienced with JavaScript. I have two functions. One is called when my upload begins. The next is called when my upload ends.
In the first function, a variable is created, a unique id used for the upload. What is the best way to go about reusing it in my second function since it is not global? The reason I defined it within my function is because every time a user clicks the upload button, the function is called and a NEW id is created for that upload, that is why I do not want to define it outside because then the same id would be served for a second upload unless the page is refreshed.
Anyone got any suggestions?
function uploadstart() {
function makeid() {
var text = "";
var possible = "abcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 32; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
var rand_id = makeid();
}
uploadfinish(){
//rand_id will be undefined
}

Pass in that var as a parameter
uploadstart(){
function makeid()
{
var text = "";
var possible = "abcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < 32; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
var rand_id=makeid();
//Pass in rad_id
uploadfinish(rand_id);
}
uploadfinish(radomID){
//rand_id will be undefined
}

Try declaring rand_id in global scope (before everything)
var rand_id;
function bla....

The solution to this problem depends on how and where you use those two functions. If you pass them as callbacks to another function from some ajax library, or something like that, and if you control that library call, you could use a closure.
So, if for example you do something like this when an upload is begun:
Library.foo(..., uploadstart, uploadfinish);
You could define makeID as a global function, and then bind the generated id to your callbacks using a function like this:
function bind_id(rand_id, my_function) {
return function() { // return a closure
return my_function(); // my_function is executed in a context where rand_id is defined
}
}
Then you define your callbacks using rand_id as if it were global (actually, it will defined in the closure):
function uploadstart() {
// use rand_id as you wish
}
function uploadend() {
// use rand_id as you wish
}
When you need to call your Library.foo function, first generate the rand_id, then bind it to the start and end callbacks:
var new_rand_id = randID();
Library.foo(..., bind_id(new_rand_id,uploadstart), bind_id(new_rand_id,uploadend));
This way you'll pass to foo not the original uploadstart and uploadend, but two closures where rand_id is defined and i the same for both, so that callback code can use that variable.
PS: closures are one of the most powerful and trickiest features of javascript. If you're serious about the language, take your time to study them well.

What do you do with the rand_id once you've created it? Could you not just call uploadfinish with the rand_id as a parameter?
function makeid()
{
...
}
var rand_id=makeid();
uploadfinish(rand_id);
}
uploadfinish(id){
//rand_id will be 'id'
}
[EDIT] Since you said you need to call the function externally, check out this page for details about callbacks:Create custom callbacks
function doSomething(callback) {
// ...
// Call the callback
callback('stuff', 'goes', 'here');
}
function foo(a, b, c) {
// I'm the callback
alert(a + " " + b + " " + c);
}
doSomething(foo);
That will call doSomething, which will call foo, which will alert
"stuff goes here".
Note that it's very important to pass the function reference doSomething(foo),
rather than calling the function and passing its result like this: doSomething(foo()).

Related

Invoke a JavaScript function with parameter in a function

Today, I saw the following code below:
log_execution_time = require('./utils').log_execution_time;
var fib = function fib(n) {
if (n < 2) return n;
return fib(n - 1) + fib(n - 2);
};
var timed_fib = log_execution_time(fib);
timed_fib(5);
>>> Execution time: 1.166ms
I am curious about function log_execution_time. I don't know how it is.
You can see the input of log_execution_time is a function. How can it call the function with parameter? But all of the methods from w3school need a parameter when calling a function. I assume:
var log_execution_time = function (input_function){
console.time("Execution time");
// input_function
console.timeEnd("Execution time");
}
Thanks and regards
I think the OP is specifically about how the 5 parameter gets passed to the function input_function
Functions are first class objects in JavaScript. You can set identifiers and pass their references around just the same as any other object.
log_execution_time(fib); does not invoke fib, it passes a reference to fib into the log_execution_time function as the first argument. This means the internals can reference fib
timed_fib is a function which can reference the closure from that invocation of log_execution_time due to when it was created, so it can hence invoke the reference to fib as desired
Here is a simple example;
function log(msg) {
console.log(msg);
}
function wrap(fn) {
return function () { // some anonymous function to be our wrapper
console.log('Wrapped:');
fn.apply(this, arguments); // this line invokes `fn` with whatever arguments
// that were passed into the anonymous function
};
}
var foo = wrap(log);
foo('Hello World'); // logs
// Wrapped:
// Hello World
We could also have used the more usual way to invoke fn, for example fn("fizz buzz");, instead of .apply but that would mean we needed to know more about how to invoke fn, which could have been anything
Useful stuff:
Function.prototype.apply
Function.prototype.call
This is known as function currying, in this case the function is being curried with a parameter that also happens to be a function. It may look something like this:
function logTime(f) {
return function() {
var s = new Date();
var r = f.apply(null, arguments);
var e = new Date();
console.log('Time taken ' + (e-s));
return r;
}
}
function numberlogger(n) {
console.log("logged number: " + n)
};
var timedlogger = logTime(numberlogger);
console.log(timedlogger(2));
We call logTime, passing in numberlogger as an argument. Functions in JavaScript are objects and can be passed around like anything else. The logTime function returns a different function that is then stored in timedlogger. When we invoke timedlogger, we're actually invoking the function that logTime returned. That uses a couple of variables to keep track of the start and end times for timing, but uses apply (which every function in js has) to call the original function (numberlogger) whilst passing in any arguments supplied.
I suggest reading up on Functions in Javascript. Here's a nice article from the Mozilla Developer Network (MDN) which is in my opinion, a much better resource than w3schools
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions
To answer your question though, functions in javascript are first class citizens, and what that means is that you can think of them as any other object (string,boolean,number etc). They can be saved in variables and they can be passed as arguments into other functions.
In your example, log_execution_time will actually return a function which is essentially a wrapper around the fib function that gets passed to it
The code can be like this:
var log_execution_time = function (input_function){
var f=function(args)
{
var t1=new Date().getTime();
input_function(arguments);
console.warn("Execution time:" +(new Date().getTime()-t1).toString());
}
return f;
}

which is the more effeicent way to create a simple callback in javascript?

I have a function that calls array.forEach with a callback, would it be better to create the callback outside of the function like this
foo=(function(){
var f=function(v){
//long function
};
return function (){
array.forEach(f);
};
}());
or just put it inline like this
function foo(){
array.forEach(function(v){
//long function
});
}
Since //long function is only created once or is it cached or something in example two?
Edit:
when I try
a=function() {return function(){};} a()!==a()
But when I do
a=(function() {
var a=function(){};
return function(){
return a;
};
}());
a()===a()
So does that mean less objects are created using number two?
In both cases you're always returning references to the same function. By the time your code runs, the JavaScript interpreter has already parsed the whole file and created all the functions in memory. It's not creating a whole new copy of the function's code every time you return it.
The above is actually a little too simplistic, because JavaScript supports closures, which let you get different effects from returning the "same" function. Consider the following code:
function makeGreeter(salutation) {
return function(addressee) {
return salutation + ", " + addressee + "!";
}
}
var sayHelloTo = makeGreeter("Hello");
var sayGoodbyeTo = makeGreeter("Goodbye");
var helloWorld = sayHelloTo("World"); // "Hello, World!"
var helloUniverse = sayHelloTo("Universe"); // "Hello, Universe!"
var goodbyeWorld = sayGoodbyeTo("World"); // "Goodbye, World!"
var goodbyeUniverse = sayGoodbyeTo("Universe"); // "Goodbye, Universe!"
Clearly the makeGreeter function can't really return exactly the same thing every time, because makeGreeter("Hello") and makeGreeter("Goodbye") must produce different functions. So you'll get two different function objects from those calls, but they're not complete copies of the function's code. Instead they'll share the same code, but hold different values for the salutation parameter used by that code.

Understanding JavaScript Closures - Freeze variable passed to callback

I do not yet have a basic understanding of JavaScript closures;
I have a question regarding a specific situation that perhaps is also basic and common example:
Count from 1 to 3 in 3 seconds
See JSFiddle here: http://jsfiddle.net/nAh8x/
The code:
var i,
t;
t = 0;
// Case A
for( i=1; i<=3; i++ ) {
setTimeout( function() { log(i); }, t );
t += 1000;
}
// Case B
for( i=1; i<=3; i++ ) {
setTimeout( wrapper(i), t );
t += 1000;
}
function wrapper(i) {
return function() { log(i); };
}
// Log utility function
function log(msg) {
$('#log').append( msg + '<br />' );
}
Case A doesn't work.
It's clear to me why: every time the function inside setTimeout is called and accesses the i variable, its value has already reached 4.
Case B works.
When wrapper(i) is called it returns
function() { log(i); };
and the above return value (a function) is what goes inside setTimeout. What goes inside setTimeout is exactly the same as Case A
But this time, the i variable have been "frozen" with the value at the time of the call.
Why using the wrapper function let the passed value to be frozen?
That's not completely clear to me.
Closure is an environment which is created with variables scope and nested function by calling of outer function,
Every time the wrapper() is called there would created each different environment for below's function
function wrapper(i) {
return function() { log(i); };
}
Here is the i's value would be same as when wrapper() is invoked. Each time the i's value would be private for that particular environment which made by invoking wrapper() outer function.
The wrapper function has it's own i that is locally scoped to it.
This receives the value of the other i at the time wrapper is called.
It might be clearer if you rewrote it as:
function wrapper(notI) {
return function() { log(notI); };
}
The variable i used inside wrapper is the one the has been passed (as a copy) as the formal parameter to wrapper. It's not the same i as the one inside your for loop - you could rename that variable to anything you like and the code would still work.
It's frozen because it has the value it had each time wrapper was originally called.

overriding a javascript function's return statement

Assume I have a js function. From some other point in the program, I want to run its code, but not its return statement. In its place, I would like to run some other return statement that references the variables in the scope of the original function.
Is there a way to do this, other than loading up the function source, replacing the return, and using eval on the result? Minimal modification of the original is possible, though it should not affect the original's performance by adding e.g. an extra function call.
You could try something like this, but I'm not sure it meets your conditions.
Edit: Fixed to work in jsfiddle
// Modified to set all "shared" variables as "members" of the function.
var test = function() {
test.val = "one";
test.val2 = "two";
return 1;
}
// Using different result
function test2() {
test();
return test.val2;
}
Unless you're able to restructure your methods to accommodate a callback or introduce some other parameter-based logic-flow (not an option for 3rd party code), you're out of luck.
Here's a callback sample (fiddle, credit to dzejkej's answer)
function foo(callback) {
var x = 2;
// pass your values into the callback
return callback ? callback.call(this, x) : x * 2;
}
document.write(foo());
document.write("<hr/>");
// specify the parameters for your callback
document.write(foo(function(x){ return x * 4;}) );
You can introduce a callback function that will get called if available otherwise "standard" value will be returned.
function test(callback) {
// ...
return callback ? callback.call(this) : /* original value returned */ "xyz";
}
test(function() { /* "this" is same as in test() */ });
EDIT:
If you want to pass variables inside callback then you just list them in the .call() function.
Example:
function test(callback) {
var a = 4;
var b = 2;
// ...
return callback ? callback.call(this, a, b) : a * b;
}
test(); // 8
test(function(a, b) { return a + b; }); // 6
See this fiddle.
Provided that you would keep variables of the outer scope function within a single object, you could try something like the following:
function original(a, b, c, rep) {
var data = {};
// Do some fancy stuff but make sure to keep everything under data
data.a = a.replace(/foo/, 'bar');
...
if ( Object.prototype.toString.call(rep) === '[object Function]' )
return rep.call(data);
return data;
}
function replacement() {
return 'foo' + this.a;
}
// Now let's make use of both the original and the replacement ...
console.log(original('foo', x, y)); // => {a: "bar", b: ...}
console.log(original('foo', x, y, replacement)); // => {a: "foobar", b: ...}
Hope, it's what you where asking for.
cheers
I think you really misunderstand the concept of return statement. The return statement of a function will simply return a value, or an object, or undefined if there is no return parameter specified.
If all you're trying to do is execute a function but "not its return statement" than you would just invoke the function and not do anything with the returned value/object:
However, if what you mean is that you would like to execute a function but not execute the "parameter" to its return statement then that literally means to selectively execute an arbitrary portion of the body of a function. And as far as I know that is not possible (without using reflection to get the function definition, modify the definition, and then dynamically invoking the modified version - which you said you didn't want to do).

Meaning or source code for callback() in node.js chat app

I'm trying to go through the source code for the node chat demo seen here. In the server.js file and fu.js file there is a function referenced as callback() seen here:
function loadResponseData(callback) {
if (body && headers && !DEBUG) { //if they already have value
callback();
return;
}...
but as far as I can tell this function is never defined and I cannot find it as a module function of node.js, a function of jquery or a standard function for javascript.
I think I understand how callback functions work but I'm not familiar with this call and it is used frequently enough in this app that I would like a firm understanding of what it is and where it comes from.
So my question is three fold:
1) where is the function based: (javascirpt, jquery, node.js, particular to this app)
2) where can I find the source code for this function?
3) how is this function interacting with the functions it is called in?
It is the argument of the loadResponseData function. If you call loadResponseData like this:
loadResponseData(function () {
res.writeHead(200, headers);
res.end(req.method === "HEAD" ? "" : body);
});
then callback() in loadResponseData will execute
res.writeHead(200, headers);
res.end(req.method === "HEAD" ? "" : body);
EDIT to clarify the question in comments:
You could say it's a feature of JavaScript. The important thing here is that JavaScript is a functional language: it has functions as a data type in their own right. Thus, you can save them in variables (and indeed, that's all every function name in JS is - a variable with a function as its content), and pass them along in an argument list (as is demonstrated here). There is nothing magical about the name callback - it could have as well been fn or whoopsie7. To demonstrate:
var doubleAndOne = function(a) {
return a * 2 + 1;
}
function doItTwice(k, whoopsie7) {
whoopsie7(whoopsie7(k));
};
doItTwice(5, doubleAndOne); // result is 23
function(...) {...} is called an anonymous function: it is pure function value, taking some arguments and doing something with them, but it is not assigned to any name. To make a function with a name, you can assign this to a variable, or pass it as a parameter, just like you could with any other value. For example, there is very little difference between:
var five = function() { return 5; };
var doubleFuncValue = function(fn) { return fn() * 2; };
doubleFuncValue(five); // result 10
and
var five = 5;
var doubleNumValue = function(n) { return n * 2; };
doubleNumValue(five); // result 10

Categories

Resources