i am starting to look at JS in more detail and after testing out some code i have come up with this situation:
var hello = function ()
{
console.log(arguments);
return (function(x,y){console.log(arguments);return x*y;});
}();
console.log(hello(2,5));
The output from the console is as follows:
[object Arguments] { ... }
[object Arguments] {
0: 2,
1: 5
}
10
Can someone please explain the behavior as i cannot get my head around it.
I understand the the first function is an IIFE and it is being executed immediately when it is created. My only problem is how does the passed parameters be passed to the internal function?
Thanks in advance for the information and comments
Alright, let me see if I can unwrap this for you:
var hello = function ()
{
console.log(arguments);
return (function(x,y){
console.log(arguments);
return x*y;
});
}();
console.log(hello(2,5));
First, I'm going to split out the IFFE into a function statement. It will work the same, but be more like traditional code:
// Create our function
function action(x, y) {
console.log(arguments);
return x*y;
}
var hello = function ()
{
console.log(arguments);
//Here we are returning a REFERENCE to a function that already exists.
// We are *not* running the `action` function -- just getting its
// reference so it can be called later.
return action;
}();
// At this point in time, if you did a
console.log(hello)
// You'd see that it just points to the `action` function -- since that is what the
// IIFE returned.
console.log(hello(2,5));
The value hello is now our action function.
The IFFE syntax has the following advantages:
Since it is an anonymous function, you aren't using a name or cluttering the global object.
The code is more "in-line" instead of being split into two separate pieces.
Might help, by the way, if I explain the difference between a function statement and a function expression.
A function statement looks like this:
function functionStatemnt() {
...
}
The functionStatement is available at compile done. That code doesn't need executed in order to be available.
A function expression is more like:
var functionExpression = function() {
...
};
And an IFFE is a function expression that immediately invokes. Gives you a way to create a scope and "hide" variables.
var myCounter = function() {
var counter = 0;
return function() {
return counter++;
}
}
console.log(myCounter());
console.log(myCounter());
console.log(myCounter());
Related
I'm trying to understand exactly how this Once function by David Walsh works:
`
function once(fn, context) {
var result;
return function() {
if(fn) {
result = fn.apply(context || this, arguments);
fn = null;
}
return result;
};
}
// Usage
var canOnlyFireOnce = once(function() {
console.log('Fired!');
});
canOnlyFireOnce(); // "Fired!"
canOnlyFireOnce(); // nada
`
I understand it takes a function as a argument, and returns a function that calls the passed function only once.
But I'm trying to understand what each part is doing. Can anyone help explain? especially this part:
result = fn.apply(context || this, arguments);
Why the OR sign? what is "this" and how is it getting the arguments from fn? What purpose does 'context' serve?
I wrote a similar once() function for school that returns the result of the passed function, and stores the result to return it again if the function attempts to get called again. It took a lot of trial and error, and I'm just trying to get a firm grasp on all the component parts of how this works.
`
function add(x, y) {
return x + y;
}
function once(fn) {
let timesRan = 0;
let result;
function doOnce() {
if (timesRan === 0) {
timesRan = 1;
result = fn.apply(this, arguments); //I don't understand how this gets the arguments from AddOnce
console.log(`did it once: ${result}`)
return result;
} else {
return result;
}
}
return doOnce;
}
var addOnce = once(add);
console.log(addOnce(1, 2)); // test first call, expected value: 3
console.log(addOnce(2, 5)); // test second call, expected value: 3
console.log(addOnce(8, 22)); // test third call, expected value: 3
`
The concept behind this in JavaScript is confusing, because when I write a function such as:
function getPersonName() {
return this.name
}
I expect that this be defined as a some object with a name attribute. Depending on the scope, I may have this be defined and no problems! But in order for a function such as the above to properly reference this, we need to tell it what it should reference when we use that keyword.
For example, it allows us to do the following:
var canOnlyFireOnce = once(function() {
console.log(this.name)
}, {name: "John"});
canOnlyFireOnce() // prints John
canOnlyFireOnce() // nada
It may be helpful to understand the bind function's use cases in JavaScript to understand why having this (no pun intended) is useful.
The meaning of the this context in function.apply is already explained in rb612's answer.
For the question about arguments, you need to know that
the arguments object is a local variable available within all non-arrow functions. You can refer to a function's arguments inside that function by using its arguments object.
Recently I've been reading the You Don't Know JS book series on Github, one snippet of code really eludes me. I simplified the code and present you the two different versions of code below:
The correct version:
var fun = function () {
console.log("this is something");
}
var func = fun; // why this line?
fun = function() {
func.call(null);
}
fun();
The wrong version:
var fun = function () {
console.log("this is something");
}
fun = function() {
fun.call(null); // why this causes error?
}
fun();
If you run snippet two, the error "Maximum call stack size exceeded" would occur.
I can not understand why the line var func = fun; in snippet one is necessary.
fun = function() {
fun.call(null);
}
fun();
You have a function that calls whatever is stored in fun, and you assign it to fun. That's just infinite recursion.
The rest of the code doesn't matter. In particular, the old value of fun is never used before the assignment fun = ... overwrites is.
What's different in the first example is that func is never overwritten, so it still keeps a reference to the first function, the one that just calls console.log.
In other words, in the first case the chain of calls goes
fun --> func --> console.log
with fun = function () { func.call(null) } and func = function () { console.log("this is something") },
whereas in the second case it goes
fun --> fun --> fun --> fun --> ...
with fun = function () { fun.call(null) }.
What's crucial here is that function() { fun.call(null); } does not capture a copy of fun. It's not like the value of fun is frozen in place at the time the function is defined, so to speak.
Instead the function captures the variable itself (not the value it had at some point). That's why when the function is called, it uses whatever value is stored in fun at the time of the call.
A simplified demonstration of the issue:
var x = "hello";
var f = function () {
console.log(x);
};
x = "bye";
f();
This code prints bye, not hello.
var fn = function example(){
console.error('Hello');
}
I want to understand how function initialization with name 'example' doesn't throw error during execution.
Secondly i understand the flow of 'fn' holds the reference of the function i'm assigning to it, were when i execute 'fn()' it works, were as when i try 'example()' it doesn't print "Hello"
Help me to know how that stuff works !!
Because you assign only name example to anonymous function. You do not create actual example function.
Your fn holds function that has it's name as example
var fn = function example() {
console.error('Hello');
}
var fn2 = function () {
console.error('Hello 2');
}
function example2() {
console.error('Hello 3');
}
console.log(fn.name);
console.log(fn2.name);
console.log(example2.name);
console.log("");
console.log(window['example']);
console.log(window['fn']);
console.log(window['fn2']);
console.log(window['example2']);
'use strict';
let worker = {
someMethod() {
return 4;
},
slow(x) {
return x * this.somemethod();
}
};
function wrapper(func) {
return function(x) {
let result = this.func(x); // **
return result;
};
}
worker.slow = wrapper(worker.slow);
alert( worker.slow(2) );
When I run this code I get this error:
TypeError: this.func is not a function
If I replace the problematic line at ** with this:
let result = func.call(this, x);
I get the expected output. In this case it's 8.
I'm wondering why the way it's written is the wrong way to get "this" ie the object worker. In other words, how does the call function get the right object i.e. worker ?
The reason it's failing is that in the problematic line (highlighted with // **), you're effectively calling worker.func(x), which does not exist; You're not referring to the passed in variable at all.
If you add a function (func) to your worker, e.g.
let worker = {
someMethod: function() {
return 4;
},
slow: function(x) {
return x * this.somemethod();
},
func: function (x) {
return x * 10;
}
};
And call as above e.g.
worker.slow = wrapper(worker.slow);
console.log( worker.slow(2) );
You'd find it works, though this is not what you really want!
In JavaScript, any function call obj.f(ArgumentList) will be desugared into f.call(obj, ArgumentList...)(see ecma-262 7.3.12)
When wrapper(worker.slow) got a call, the function slow is passed into the wrapper and it produces another function which captured func argument. However, that function returned by wrapper is not called yet.
At a moment of the function call alert( worker.slow(2) )
func mean the argument that got captured in the closure and func.call(this, x) means it will call that function with the current caller, which is worker.
Therefore, `func.call(this,x)` will be `func.call(worker, x) `
which works because `func` exists in the closure.
while this means the reference to a current caller to the function(x){ ... }
Hence, `this.func(x)` will be `worker.func(x)`
which `func` does not exist in `worker`.
if you try to insert console.log(func) and console.log(this)
in that function, you will see the difference.
I have often see expressions such as:
(function () {
var x = 1;
...
}());
How do I interpret it? syntactically, this alone is a anonymous function definition.
function() {
...
}
what the () after that? and why put it in the enclosing ()?
Thanks
Exactly the same, except that it is being invoked immediately after being converted into a function expression.
// v-----first set of parentheses makes the function an expression
(function () {
var x = 1;
...
}());
// ^-----this set is used to invoke the function
Same as if you did:
var myfunc = function () {
var x = 1;
...
};
myfunc();
or (similar) this:
var returnValue = function () {
var x = 1;
...
}();
Get rid of the names, move the parentheses around, and you can see they're not that different.
The area where I most often find this useful is in callback functions. This notation can also used in cases where you need to include a variable in a callback function, but you need the variable state to not be affected by what goes on outside the function.
var someVal = 1;
setTimeout( (function(one) {
return function() {
alert(one); // alerts a 1 even 10 seconds after someVal++;
}
})(someVal), 10000);
someVal++; // the value in the setTimeout will remain the same as it is locked inside.
In this context, setTimeout takes a function that takes no arguments. So the question of how to pass in a value to that function is answered by creating a function that takes one argument that returns a function that takes 0 arguments.
I suggest anyone wanting to learn more about the power of this notation to play around with it in the Firebug JavaScript console. Once you wrap your head around this concept, you'll start to see areas where this powerful concept can be used.