const someFnc = arg => arg("You can print that string :)");
Is just the anonymous way to make:
function someFnc (arg) {
arg("You can print that string :)");
}
The other anonymous function you define:
msg => console.log(msg)
This makes a anoynous function that takes msg and uses it to a call to console.log. Since it just calls console.log with the first argument it is a wrapper that does nothing. You can indeed just replace it with console.log:
someFnc(console.log)
Now using substitution rules we can replace a function call with the body of the function with the argument replaced for the bound variable, thus:
arg("You can print that string :)"); // replace arg with console.log
// ===
console.log("You can print that string :)");
Now when you write barewords in JavaScript, like parseInt, it is a variable. It evaluates to a function. Thus parseInt("10"); // ==> 10. In the body of your function arg is a variable that gets the value of the attribute log on the object console. It is a function just like parseInt. Variable are values and functions are also values.
When you pass a value to as function it is bound to the variable in it's definition. It can even shadow existing functions:
((parseInt, value) => parseInt(value))(Number, "10");
// => 10
So the rule is replace the bound variables with the arguments, thus it is really:
Numer("10"); //=> 10
Variables are just names for values. A function is a value you can put () after to apply, optionally with arguments within.
argisn’t self-invoked. The invocation is in the function body ofsomeFnc(arg("You can print that string :)")).someFncinvokes the functionargthat it declared as a parameter when it executes.