If I pass function to a function with same function name and handler name, which one will get precedence ? and how to access each of those two inside function in case in need to do recursion as well as refer to the passed function. See below code.
var f1,f2;
(function f(f){
return typeof f(f2); /*please check below comments for output of this line*/
})(function(f1){ return 1; });
/* this will call the passed function,why not recursion will not happen here? */
The function parameter gets precedence over the function's own name. If you shadow or overwrite a variable, you can't access it (unless it's a shadowed global).
Solution is to use different names.
The recursion doesn't happen simply because the argument of the function get precendence than the function itself. here is an example that shows it:
(function f (f) {
return f.name;
}) (function funcName () { }); // this will return funcName
if we change the name of the argument to f1, f will become the reference of the function itself
(function f (f1) {
return f.name;
}) (function funcName () { }); // this will return f
I see that you use jquery. So I want to ask where do you have declared your functions? inside
<script type="text/javascript">
$(document).ready(function(){
function f(){
return 'this is local function inside anonymous function, so it's invisible for recursion in aside of current document ready'
}
});
//or here?
function f(){
return 'this function is a window object property, and must be visible for recursion';
}
</script>
Related
I'm getting the following error in the console:
Uncaught ReferenceError: jason is not defined
Here is my javascript:
$(document).ready(function jason() {
console.log("test");
});
var addEvent = function(object, type, callback) {
if (object == null || typeof(object) == 'undefined') return;
if (object.addEventListener) {
object.addEventListener(type, callback, false);
}
};
addEvent(window, "resize", jason());
Thanks so much for the help!
When you put it inside $(document).ready() it is not available outside that function. Make it global and define it without $(document).ready(), but this will run even before the page loads.
function jason() {
console.log("test");
};
var addEvent = function(object, type, callback) {
if (object == null || typeof(object) == 'undefined') return;
if (object.addEventListener) {
object.addEventListener(type, callback, false);
}
};
addEvent(window, "resize", jason());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
In Javascript, there are many ways to define functions. They generally fall into two categories though: function declarations and function expressions.
Function declarations look like this:
function jason() {
console.log("test");
}
A function declaration has global scope regardless of where it is in the code, and it can be called earlier in the program than where it is defined. (Edit: actually, if a function declaration is nested within another function, then it can only be called within that outer function)
Function expressions look like this:
// Anonymous function expression set to a variable
let jason = function() {
console.log("test");
};
// Named function expression set to a variable
let jason = function freddy() {
console.log("test");
};
They are scoped just like any other variable. They must be set before they can be called.
In your case, you created jason() as a function expression but didn't assign it to a variable. You did name it jason, but that name only works inside of the function (like for recursion), not elsewhere. If you were only going to use the jason() function as an argument to $(document).ready(), then defining as you did would be ok. But since you seem to want to use jason() in more than one place, you either need to 1) change it a function declaration or 2) make it a function expression that is assigned to a variable prior to being passed to $(document).ready() and addEvent().
By the way, when passing a function as an argument, you need to leave off the parentheses, like this:
$(document).ready(jason);
addEvent(window, "resize", jason);
If you do the following instead, it will execute jason() and pass the value it returns to each of those funtions. In this case, that value would be undefined.
// Not what you want
$(document).ready(jason());
addEvent(window, "resize", jason());
Function expressions can be given a name, but as noted in the MDN link, the name is only available within the function's body.
Function declarations which cause a named function to be hoisted to the top of the function or script element in which they reside are also function statements.
Naming and providing the code for jsan as an argument value for a call to ready prevents it being treated as a statement and creates a function expression.
Obviously if you want to call or reference the jsan function in multiple places it needs to be declared in the scope of everywhere it's referenced - which could require creating a global function or declaring it in a common outer function, depending on the structure of the code.
Jason is wrongly define. Just check the below code, first you define a function and then call it.
$(document).ready(function() {
addEvent(window, "resize", jason());
console.log("test");
});
var addEvent = function(object, type, callback) {
if (object == null || typeof(object) == 'undefined') return;
if (object.addEventListener) {
object.addEventListener(type, callback, false);
}
};
function jason(){
console.log("call jason function");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
You can write your code just in document .ready function().
$(document).ready(function(){
console.log("test");
})
var addEvent = function(object, type, callback) {
if (object == null || typeof(object) == 'undefined') return;
if (object.addEventListener) {
object.addEventListener(type, callback, false);
}
};
addEvent(window, "resize");
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I though that once createFunction runs I'll have access to the inner function.
function createFunction() {
function printHello() {
return console.log("hello");
}
return printHello;
}
// Both of these return undefined
createFunction(printHello());
createFunction.printHello();
Any thoughts?
Proper syntax is:
createFunction()();
... or, a bit more wordy:
const returnedFunction = createFunction();
returnedFunction();
... as printHello name makes any sense only within createFunction, but its value is actually returned by that function. And yes, it's perfectly ok to place any number of () in sequence you want.
As a sidenote, returning the result of console.log('hello') makes little sense: logging itself is a side effect, no need to check its result.
I though that once createFunction runs I'll have access to the inner function.
No, you cannot access a variable that is inside of a function outside of it. If you call a function those variables exist, but you cannot access them. However if a value gets returned, you can work with the function call as if it would be that expression. In your case you return the function so you can access it as:
var print = createFunction();
print();
Or as a oneliner:
createFunction()();
In your code createFunction returns another function, so to execute inner function you must call inner function by appending () after return value of createFunction i.e createFunction()();
createFunction() give printHello = function definition
createFunction() () same as printHello**()**
Also if we simplify your code we can re-write as
function printHello() {
console.log("hello");
};
function createFunction() {
return printHello;
};
console.log("return value of: createFunction()");
console.log(createFunction());
console.log("return value of: createFunction() () --> printHello()");
createFunction()();
I have tried folllowing two ways of referring a function:
First
let a = function() {
somefunction();
}
Second
let a = somefunction;
Where somefunction is the following in both cases:
function somefunction() {
alert("hello");
}
Is there any difference between these two ways?
Yes, there is a difference between your two examples.
In the first case, you are defining a new anonymous (unnamed) function which calls somefunction. You are then assigning your new function definition to the variable a. a holds a reference to your new function.
In the second case, you are simply assigning your original function of somefunction to the variable a. The variable a then holds a reference to somefunction. You are not creating a new function as you are in the first case.
I think this example may make the difference clear. arguments is an array like object that contains each of the arguments passed to a function.
Try running each of these lines on your favorite browser console.
var somefunction = function() { console.log(arguments); };
Your first example demonstrates defining a named function a that closes around the named function somefunction.
var a = function() { somefunction(); };
Your second example makes a reference, b, directly to somefunction. This makes invoking b the same as invoking somefunction.
var b = somefunction;
Now if you call each of these a and b with some arguments you will see the difference.
=> a('a', 1);
[]
=> b('a', 1);
['a', 1]
In the first case the arguments object is empty. That's because the arguments that were passed to a were not forwarded onto somefunction.
In the second case the arguments are available to somefunction, because some function is being called directly.
Here is how you could redefine a so that it were functionally equivalent using apply
var a = function() { somefunction.apply(this, arguments); }
Running this at your console prints the argument array.
=> a('a', 1);
['a', 1]
var a = function(){
somefunction();
}
Is an Anonymous Function attributed to a variable.
somefunction :function() {
alert("hello");
}
Is an declaration of a function throungh the Object Literal notation.
The diference are shown when you are creating an object. The anonymous function are not acessible as a "public" method, instead in the Object Literal notation, that are acessible from outside.
As Douglas Crockford said, in JS the Good Parts, the first declaration are just a function and the second one could be a method.
In the first case, you are creating a function which calls someFunction(), then you assign that function to a, so now calling a() calls an anonymous function which in turn calls someFunction().
In the second case, a and someFunction become the exact same thing, calling a() is the same as calling someFunction().
The way you're setting var a by accessing the function is clearly out of scope.
So I suspect you have a typo : instead of = :
var somefunction = function() {
alert("hello");
};
somefunction(); // hello
...Now that your first and second makes sense with the code above:
Anonymous Function stored in variable:
var a = function(){
alert('Hey');
somefunction();
};
a(); // Hey // hello
Variable as Function Reference
var a = somefunction;
a(); // hello
In the other case than:
var objLiteral = {
somefunction : function() {
alert("hello");
}
};
var a = objLiteral.somefunction;
a(); // hello
How do I explain the role of the arguments passed in the beginning vs end of a wrapped Javascript closure as the one shown below?
(function($, window) {
return $(function() {
return alert("js!");
});
})($, window);
The first appearance are function parameters, the second is passing values for those parameters when executing the function.
Keep in mind, the parameters to the function don't need to match the names being passed (this could, in fact, cause confusion later on):
(function(jQuery, w) {
return jQuery(function(){
return alert("js!");
});
})($, window);
Would work the same way.
In that way you are passing arguments that will be safe in the scope from an overwrite in the future. For example:
var a = 1
(function(a){
setTimeout(function(){
console.log('This variable is still safe', a);
},2000)
})(a)
a = 0
console.log('has changed', a)
So in your example you can be sure that $ and window will be that what you are expecting.
It may be easier to explain if you change the argument names and name the function
(function init($, win) {
return $(function() {
return alert("js!");
});
})(jQuery, window);
The init function is being passed the parameters jQuery and window immediately as it's defined, they are available as arguments to the init function as $ and win
If you break it out into the equivalent code, that may also be easier to understand
function init($, win) {
return $(function() {
return alert("js!");
});
}
init(jQuery, window);
The set of parameters on top is where the parameters are recieved, and the set of parameters on the bottom is where they are passed.
They're ensuring that their closed copies of the global variables don't get reassigned outside of the closure. It is a way of protecting your code against other (potentially poorly written) code. Consider this example:
var $ = 'foo';
var blah = (function($) {
return function () {
alert($);
};
})($);
var shizzam = (function() {
return function () {
alert($);
};
})();
// someone evil overwrites my $ var
$ = 'bar';
// blah still works
blah();
// but shizzam is now borked
shizzam();
http://jsfiddle.net/xfTcq/
When a function returns another function it can be enclosed on parentesis to be immediate executed.
The last parenthesis are the passed arguments to it.
You can do some tests do understand:
var a (function(){});
typeof a;
a.toSource()
typeof (function(){});
(function(){}).toSource()
I understand you can pass a function as an argument to another function like so
var fn = function(){alert('Hello')}
function outer(a,fn){
fn();
}
How can you pass an anonymous function to another function and have it invoked within the function after taking a parameter from the outer function?
function outer(function(x){alert(x);})
{
var xVar = "foo";
//..would liked to pass xVar to the anaonymous function
//passed as a param to the function so that "foo" is displayed as message...
}
Please note changing the signature of outer would be the last choice.
You're confusing function invocation (calling a function) with function declaration (defining a function). Here's how do what you ask:
// declare the outer function
function outer(func)
{
var xVar = 'foo';
func(xVar)
}
// now invoke it
outer(function (x)
{
alert(x);
});