I am trying to understand how an anonymous function inside of a callback function is invoked.
For example:
const callbackExample = function(param, callback) {
console.log('This is an example of a callback function');
callback(param);
};
callbackExample('What', function(param) {
console.log(param);
})
My question is how does a anonymous function get invoked? If I substitute the callback to equal the anonymous function below.
Is the callback being substituted for the anonymous function.
Does the callback === function(param) { console.log(param) }
What I mean is I cannot invoke the function like this.
function() { console.log('Not') } ();
There are only three ways to declare and invoke a function.
assign a anonymous function a name: function expression
give a function a name: function declaration
Immediate Invocation function express
My theory is when not using a function express or function declaration for the callback function then Javascript parses the code and detects a anonymous function and uses iife to invoke the anonymous function.
I cannot find anything on the internet nor an api that describes what is happening behind the scenes, so I ask can somebody explain this to me.
IIFE (immeadiately invoked function expression) is just a name coined by the community for this specific construct:
(function() { /*...*/ })()
It's a function expression, that is directly followed by a function call to that function. That's it. You don't have an IIFE in your code.
My question is how does a anonymous function get invoked?
Functions get invoked using a reference to them, their name is just a debugging feature (and it's a reference to the function itself inside the functions body). Functions don't need a name:
let test = function /*irrelevant*/ () { };
let test2 = test;
test(); test2();
If you use a function declaration, the name is not only used as the function name, but also as the name of a variable that references the function:
function named() { }
is barely equal to (let's ignore "hoisting" here):
var named = function named() { }
If you invoke a function using a function expression as one of it's arguments:
function called(reference) { }
called(function irrelevant() { })
then the function expression gets evaluated, a function gets created, and a reference to it gets passed to the called function as an argument, which can then be accessed using the reference variable.
Related
So I'm unit-testing my code and I face a problem with testing an anonymous function being called inside the function that I'm unit-testing.
The reason for why I didn't make the anonymous function an instance named function, is because I need the closure of some of the variables from the unit-tested function to be used inside the anonymous function.
Example to illustrate:
function funcBeingTested(done, arg1) {
var self = this;
...
self.array.push({
"arguments": [
"x", "y", function (error, result) {
// do some stuff with arg1...
done(error, arg1);
}, "z"
]
});
...
self.run(); // Eventually will call the anonymous function above from 'self.array'
}
Now, my question is there a way to test what's going on inside that anonymous function using sinon.js ? Someway I could call it with specific arguments as part of the unit test of funcBeingTested() ?
Edit:
To clear up any misconception about what I'm trying to achieve,
I wish to be able to unit test the anonymous function it-self and cover all it's possible branches to get 100% coverage. I already know how to check if the done() callback was called, and with what args using sinon.js, the problem is how would I test the anonymous function in an isolation, and call it with specific arguments to cover all possible branches.
You can test the anonymous function by defining the done function and spying on it. You need to know if this function is called with the right arguments when the anonymous function is called.
For example:
// Define the `done` function.
var doneFunction = function (error, args) {
// do something
};
// Spy on the `done` function to register calls.
var doneSpy = sinon.spy(doneFunction);
// Test the funcBeingTested
funcBeingTested(doneFunction, someArg);
// Check that doneFunction was called
assert(doneSpy.calledWith(someArg));
You can read more about the Spy API for Sinon
Let's assume that I define a self-executing function like the following :
({
function1: function(){//...}
function2: function(){//...}
})
How can I call function2 from inside function1 ?
(I tried calling it just like : function2(); and this.function2(); , none worked, both returned error : function2() or this.function2() is not a function)
Actually this is part of the Aura framework, so maybe it is specific to this framework.
There are several things wrong here. First, this is not a self-executing function. This is an object with two functions defined inside it and wrapped in parentheses, which make it invalid. Something like this would be a valid JavaScript object:
object1 = {
function1: function(){
console.log('function1 called!'); // logs the text 'function1 called!' to the console
},
function2: function(){
console.log(this); // logs the details of `object1`
this.function1();
}
};
object1.function2();
Equivalent functionality using an anonymous function would look something like this:
(function (){
console.log('anonymous function called!');
})();
Note the lack of curly brackets surrounding the anonymous function. Unlike the functions in the object, the anonymous function isn't a member of any object. Also note the last set of parentheses at the end, those are what triggers the execution of the anonymous function that has just been defined.
JavaScript functions: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions
I want to create a closure dynamically. See code below for explanation.
function myFunction(){
parentScopedVar(); //Would like to be able to call without using 'this'.
}
function myDynamicFunc(dynamicClosure){
//What do I need to do here to dynamically create
//a var called 'parentScopedVar' that can be referenced from myFunction?
myFunction.call(self);
}
myDynamicFunc(
{
parentScopedVar : function() { alert('Hello World'); }
});
Javascript uses lexical scope (based on where the code is declared), not dynamic scope.
If you are determined to try to do something that the language doesn't really encourage, you can force a string of code to be evaluated in your current execution context using eval(string of code here). In fact, you can do all sorts of odd things with eval(), but I'd much rather write code in a way that leverages the strengths of Javascript than to use a coding style that goes against the main design theme of the language (that's my opinion).
It's not entirely clear to me what problem you're trying to solve, but you can just pass a function as an argument and then call it via the argument from the called function.
// declare your function that takes a function reference an argument
function myFunction(callback) {
// call the function that was passed
callback();
}
function myDynamicFunc(){
// declare a local function
function myAlert() {
alert('Hello World');
}
// call your other function and pass it any function reference
myFunction(myAlert);
}
This will not pass an entire execution context. To do that, you'd have to package up the context in an object and pass a reference to the object, then dereference the properties from the object. That is typically how you pass an environment in JS.
You can use locally declared functions to provide access to parent scope from a callback (again lexical scope):
// declare your function that takes a function reference an argument
function doSomething(callback) {
// call the function that was passed
callback();
}
function myFunc() {
var myLocal1 = "Hello";
var myLocal2 = "World";
function callback() {
// when this is called, it has access to the variables of the parent scope
alert(myLocal1 + " " + myLocal2);
}
doSomething(myFunc);
}
You can even use it as a lasting closure:
// declare your function that takes a function reference an argument
function doSomething(callback) {
// call the function that was passed
callback();
}
function myFunc() {
var myLocal1 = "Hello";
var myLocal2 = "World";
function callback() {
// when this is called, it has access to the variables of the parent scope
// which are still alive in this closure even though myFunc has finished
// executing 10 minutes ago
alert(myLocal1 + " " + myLocal2);
}
// call the callback function 10 minutes from now,
// long after myFunc has finished executing
setTimeout(callback, 10 * 60 * 1000);
}
Here are some reference articles on lexical and dynamic scope in Javascript:
Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?
Are variables statically or dynamically "scoped" in javascript?
What is lexical scope?
Does anyone know how to pass parameters to a callback function that you cannot alter?
So here is the code I'm trying to implement (It is a siesta testing method):
Base.js:
waitForComponentQueryVisible: function (parentNext, parameters) {
var th = this,
query = parameters.query,
scope = th,
callback = callFunct,
timeout = 10000;
//The function inside here (returnToParentTester(parentNext, parameters)) is from Base.js
callFunct = function () {
scope.returnToParentTester(parentNext);
}
this.test.waitForComponentQueryVisible(query, callback, scope, timeout);
},
The problem here is of two parts:
1. I cant get the scope just right so I can use the returnToParentTester method that is found in Base.js
2. I want to pass in parentNext into the method but cannot do that when defining it as a callback
this is the method I need to run as the callback:
Base.js:
returnToParentTester: function (parentNext, parameters) {
debugger;
if (parentNext) {
parentNext.call(undefined, parameters);
} else {
this.test.fail('--Developer Error-- undefined parentNext ' +
'variable. All the chains are going to fail');
}
},
I can't get the scope just right so I can use the returnToParentTester method that is found in Base.js
Use the call method to change the scope:
Base.returnToParentTester.call(myScope)
I want to pass in parentNext into the method but cannot do that when defining it as a callback
Use an anonymous function as a callback and pass parameters within its scope:
$("body").click(function(e){foo(e.target,bar,baz)})
then let it do the work:
function foo(myScope, next1, param1)
{
Base.returnToParentTester.call(myScope, next1, param1)
}
References
Fast JavaScript max/min
Mixins and Constructor Functions
Function.prototype.apply revisited
applyFunctionArguments - argument injection technique in JavaScript
Functional JavaScript, Part 3: .apply(), .call(), and the arguments object
On about line 18, make the anonymous function with the code 'window.didExecute = true' execute.
var anonymousFunction = function(){};
(function(){window.didExecute=true;})
doesn't work, why?
Because the function is never executed. Use an immediately invoked function expression:
(function(){window.didExecute=true;})();
The () at the end is what actually makes it a function call, resulting in the body of the function executing.
If you weren't using anonymous functions, your code would be the same as doing:
function foo() {
window.didExecute = true;
}
Then never calling foo().