Function name not found due to reference error - javascript

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>

Related

how does this function expression work?

Function express CANNOT be used before being declared correct? But is also passed in a keypress function as well. How is this magic happening?
I am doing a code along and noticed it while I was looking over it.
var controller = (function(budgetCtrl, UICtrl){
var setUpEventListeners = function(){
//CTRLADDITEM is called below
document.querySelector(DOM.inputBtn).addEventListener('click', **ctrlAddItem**);
document.addEventListener('keypress', function(e){
if(event.keyCode === 13 || event.which === 13){
**ctrlAddItem();**
}
});
}
var **ctrlAddItem** = function(){
updateBudget();
}
};
}
})(budgetController, UIController );
This is called IIFE (Immediately Invoked Function Expression) and it's fairly common in Javascript as well as other languages like Go. Here is a simple version...
(function() {
alert('invoked immediately');
})();
This code will run immediately. Note: it is not invoked before it is defined. It is invoked by the trailing parenthesis, which come directly after it is defined. It is the exact same thing as doing this...
function doSomething() {
}
doSomething();
We have just inlined the function by wrapping it in parenthesis and then called it (), instead of calling it by name.
If you assign the result to a variable, it works just as expected, you are assigning the result of the function.
// these two are equivalent
var result = (function () {
return 5;
})();
var result = 5;
Now, the value in result will equal 5.
Why do we use them?
Most commonly, we use them to isolate the scope of your code to prevent it from polluting the global scope. For example, if this is your application code...
function MyApp() {
}
You have now polluted the global scope by creating window.MyApp. If you use a third party library that also provides a function on the global scope called MyApp, it will override yours. To prevent that, we can do...
(function(window) {
function MyApp() {}
MyApp();
})(window);
Now, MyApp is not attached to the window and we still have access to the window.
Further down the rabbit hole
You must convert your function from a declaration to an expression before you can invoke it immediately. To do this, you wrap it in parenthesis.
This does NOT work
function (){
// do something
}()
This DOES work (thanks to the parenthesis)
(function () {
})()
You can also use any unary operator instead of parenthesis. All of these work
~function () {
}()
+function () {
}()
-function () {
}()
void function () {
}()
What you have is:
// Pass ctrlAddItem
document.querySelector(DOM.inputBtn).addEventListener('click', ctrlAddItem);
// Include closure to ctrlAddItem in function expression
document.addEventListener('keypress', function(e){
if(event.keyCode === 13 || event.which === 13){
ctrlAddItem();
}
});
// later...
var ctrlAddItem = function(){ /* whatever */ }
So ctrlAddItem is declared, and therefore exists with a value of undefined before any code is executed. At the point it's used in addEventListener, its value is still undefined.
However, before the outer function completes (and before the listeners are called), ctrlAddItem is assigned a value. So by the time the listeners are called, it's a (reference to a) function.

function inside function with same name in javascript

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>

Naming a formerly anonymous function breaks

Why does this not work:
$(document).on('click','a',myFunction);
var myFunction = function() {
debugger;
}
When this does:
$(document).on('click','a',function() {
debugger;
}
I've started to learn more by naming all my anonymous functions and breaking them out into their own separate named functions.
You have to swap the lines:
var myFunction = function() {
debugger;
}
$(document).on('click','a', myFunction);
Otherwise, you would be assigning undefined as the event handler, as the variable myFunction doesn't have a value yet when you were passing it to .on.
Also: assigning a function to a variable like that doesn't make it named, it's still an anonymous function, just stored in a variable. A named function would be:
var myFunction = function someName() {
debugger;
}
See Named function expressions demystified for more details.
Instead of saying:
var myFunction = function() {
debugger;
}
you need to say:
function myFunction() {
debugger;
}
This will declare the function on the first pass so that it can be referenced during program execution.

What does the arguments passed to a javascript closure do?

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()

call prototype.call function in javascript

the problem is that when i use test.call(), it calls into my call implementation of the prototype but when i use test(), it doesnt call call(). i want to be able to use test to trigger prototype.call(). code below:
Function.prototype.call = function () {
//do something...
return this(); // call original method
}
function test() {
alert("test");
}
test.call(); //calls prototype.call()
test(); //doesnt call prototype.call()
Why would you expect test() to invoke Function.prototype.call? They're different functions.
The native .call() method that you're overwriting is not invoked every time a function is invoked. It's only invoked when you invoke it.
Invoking .call() does invoke test() because that's what it's designed to do. It expects a function as its context (this value), and invokes that function. But that doesn't mean .call() has anything to do with any other function invocation.
Here's a solution that I just whipped up (credit goes to cliffsofinsanity for pointing out a crucial error with the code and correcting it). It logs all non-standard functions called after a certain point, in the order that they were called.
// array of all called functions
var calledFunctions = [];
// custom func object that has name of function and
// and the actual function on it.
function func(_func, name) {
return function() {
calledFunctions.push(name)
return _func.apply(this, arguments);
};
}
test = function() {
alert("hi");
}
otherTest = function() {
alert("hello");
}
// put this bit somewhere after you've defined all your functions
// but *before* you've called any of them as all functions called
// after this point are logged. It logs all non-standard functions
// in the order that they are called.
for (prop in window) {
if (window.hasOwnProperty(prop) && typeof window[prop] === 'function' && window[prop].toString().indexOf('[native code]') < 0) {
window[prop] = func(window[prop], prop);
}
}
otherTest();
test();
otherTest();
console.log(calledFunctions);​
Working demo can be found here.

Categories