Let's say I have these two functions:
function fnChanger(fn) {
fn = function() { sys.print('Changed!'); }
}
function foo() {
sys.print('Unchanged');
}
Now, if I call foo()
, I see Unchanged
, as expected. However, if I call fnChanger
first, I still see Unchanged
:
fnChanger(foo);
foo(); //Unchanged
Now, I assume this is because foo
is not being passed to fnChanger
by reference, but I may be wrong.
Why does fnChanger
not change foo
to print Changed!
?
Furthermore, how can I get fnChanger
to change foo
without too much messy syntax?
PS: I'm using node.js to test all this stuff, so that's where the sys.print
comes from.
- GeeksforGeeks How to call a function that return another function in JavaScript ? The task is to call a function which returns another function with the help of JavaScript. we’re going to discuss few techniques. First call the first function-1. Define a function-2 inside the function-1. Return the call to the function-2 from the function-1.
In Javascript, functions are first class objects that can be treated just as another variable. But for the function to return its result, it has to be first invoked. When you are invoking the fnChanger (foo), the fn variable actually gets overridden with foo (). But you are not getting the result because that function was never invoked.
To call a function inside another function, define the inner function inside the outer function and invoke it. When using the function keyword, the function gets hoisted to the top of the scope and can access any of the available variables in the scope.
Since functions can be passed around anywhere, we can pass them into the arguments of functions. My first hands-on experience with anything having to do with programming in general was getting started with writing code in JavaScript, and one concept in practice that was confusing to me was passing functions into other functions.
The assignment to the fn
argument just makes that identifier to point to the anonymous function, foo
in the outer scope is not affected.
When you pass an object as an argument, one can say "references are passed by value". The assignment just replaces the location where the fn
identifier refers to.
That's how the evaluation strategy works in JavaScript.
Just before the assignment in the fnChanger
functions, the two identifiers, the global foo
and the fn
argument, point to the same function object:
--------------------------------------------- foo -----> |function foo { sys.print('Un changed!'); } | --------------------------------------------- ^ | fn -------------
After the assignment, fn
will simply point to the new function:
--------------------------------------------- foo -----> | function foo { sys.print('Unchanged!'); } | --------------------------------------------- --------------------------------------- fn ------> | function { sys.print('Changed!'); } | ---------------------------------------
How could you change it?
Well, assuming that foo
is a function in the global scope, you could do something like this:
function fnChanger(obj, name) {
obj[name] = function() { sys.print('Changed!'); };
}
function foo() {
sys.print('Unchanged');
}
fnChanger(this, 'foo');
foo(); // Changed!
The above will work because in the fnChanger
function, we require a base object and a property name, functions declared in the global execution context are bound as properties of the Global object, therefore we can re-assign its value in that way.
The line fnChanger(this, 'foo');
should be executed also in the Global scope, it will pass the this
value (which refers to the Global object in this scope) and a property name, allowing you to make an assignment to the GlobalObject.foo
identifier.
If that code were inside a function, there is no way we can get a base object, because in this "Function Code Execution Context", function declarations (variable declarations and function formal parameters also) are bound as properties of a non-accessible object, called the Variable Object (a chain of these Variable Objects, forms the Scope Chain), and if it were the case, the only workaround would be to use eval
.
More info:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With