This question already has answers here:
What is the purpose of the var keyword and when should I use it (or omit it)?
(19 answers)
Closed 8 years ago.
EDIT I want the function to be globally accessible
Why does myfunction0 work in the dom ready call and myfunction1 does not work?
external.js file
(function($) {
// functions defined like that works
myfunction0 = function() {
console.log("hello world");
}
// functions defined like that do not work
function myfunction1() {
console.log("hello world");
}
})(jQuery);
index.html
<script>
$(function () {
myfunction0(); // works
myfunction1(); // does not work not defined
})
</script>
Does the first function definition get a global scope whereas the second only a local 'in file' scope?
function myfunction1() { }
will be local to the scope in which it's defined. Not the file, but the anonymous function it's wrapped in.
myfunction0 = function() { }
declares a variable (which happens to be a function).
Since there's no var attached, that variable gets global scope.
You have not declared the myfunction0 using the var keyword so it has been declared in global scope. function declarations are tied to the scope in which they are declared.
If you add the var keyword to your myfunction0 (as you should) you'll see that neither function will be accessible:
var myfunction0 = function() {
console.log("hello world");
}
Example fiddle
Related
I've got the following Javascript situation:
// First file - the one that I can't edit
(function(){
"use strict";
function test() {
alert("a");
}
test();
})();
This is defined in a Javascript file which I cannot edit. How would I go about overriding the test() method?
Redefining the function doesn't work. The output is still "a".
// My file - trying to override the first file's test() function
(function(){
function test() {
alert("b");
}
})();
Do you have any other suggestions?
In my mind the test() method must be defined somewhere, right? And if it is defined, I can override it.
Assign the function to a variable to create locally scoped functions that will behave the same within it's own function scope.
A scoped variable has priority over a global variable. So if you define a local variable in your own function you're overriding the other defined one. within the scope you're working in of course. On the outside of your scope the global object still persists.
You can't override a function in another scope. That is why a scoped function is scoped. It will keep a reference to it's local scoped variable. That's why the scopes are generally used, so you can encapsulate and protect your code to assure your code keeps working as intended.
unless it's a publicly exposed method, you can't override it.
(function(){
var test = function() {
alert("b");
}
})();
(function(){
"use strict";
function test() {
console.log("a");
}
test();
})();
(function(){
var test = function() {
console.log("b");
}
test();
})();
The text of the file can be edited if file is requested using XMLHttpRequest or fetch, then set edited response text to .textContent of script element, append script element to document.
I had this code:
Javascript
(function() {
function read() {...}
})();
HTML
<body onload="read()">
Console said, read is undefined.
After deleting the IIFE it worked, why?
Thanks. :)
Here's a long but satisfying explanation about JavaScript scope and closures.
Since you declare read inside a function, it is local to that function.
Anything you declare inside a function will be local to it.
You can explicitly put it into global scope by assigning it as a property to window:
(function() {
function read() {...}
window.read = read;
})();
Writing
(function() {
function read() { ... }
})();
Is very nearly the same thing as writing
(function() {
var read = function() { ... } //this is different, but not significantly so
//for purposes of teaching this point
})();
and I think you should already understand why a var declared inside a function is not available outside of that function's scope.
The behavior of a function definition (function read() { ... }) is slightly different from the behavior of assigning a function expression to a variable (var read = function() { ... };) in terms of when the name of the function and the function become associated, but the two are otherwise identical.
Because it isn't defined globally. It's only been defined within the scope of that immediately invoked function. To make it global either use this:
function read() {...}
(function() {
...
})();
Or this:
(function() {
window.read = function() {...}
})();
Or better yet, just bind the onload event within the immediately invoked function:
(function() {
function read() {...}
window.onload = read;
})();
In this case the definition of read is inside the IIFE. This limits the scope of the function to the IIFE and any child functions inside of it. The handler for onload is executed in the global scope and hence doesn't have access to read
can someone please explain what the difference is between these two functions?
(function(Engine, $, undefined) { //hidden from scope
//public function below
Engine.Init = function() {
console.log("IM PUBLIC");
}
//anonymous functions below
function Login() {
console.log("IM PRIVATE");
}
})( window.Engine = window.Engine || {}, jQuery );
Specifically, I'd like to know why Engine.Init() is available in the Console but Login isn't.
Init is a property of the Engine object that refers to a function.
You can access it like any other property.
Login is a local variable within the anonymous, "immediately invoked function expression" (IIFE); like other local variables, its name is only visible within the declaring function
Engine is global because of the parameters:
(window.Engine = window.Engine || {}, jQuery)
and available in the global namespace, if you did:
Engine.Login = function(){}
That would be available globally.
The function Login is only available inside the scope of the anonymous self executing function.
There is not really a difference between the functions themselves. The only difference is that the first function is assigned to a property of an object (Engine.init) defined in global scope (window.Engine), whereas the second function is defined locally inside the immediately invoked function expression (IIFE).
Here is a equivalent, but simpler example:
function foo() {
// 1
window.globalFunc = function() {
// global/public
}
// 2
function localFunc() {
// local/private
}
}
foo();
Because the first function is explicitly assigned to a global variable, it can be accessed outside of foo, after foo was executed. localFunc is not exported and hence local to foo, i.e. it cannot be accessed and doesn't exist outside of foo.
This thing
function(Engine, $, undefined) {
...
}
is actually a closure. So everything define inside that function is available only in that scope. When you do
Engine.Init = ...
You create a property which is attached to Engine object. In your case Engine is a global object, which means that you have an access to it via the console.
A couple of days ago I have learned on my own example how bad global variables and functions are. So apparently the best solution is NOT to use them, however sooner or later I will need to reuse my variables and functions over and over again.
So my question is: Can I reuse my functions and variables without declaring them globally? Can it be done?
For example, I want to reuse my alertBox function and my containsP variable couple of times:
DEMO: http://jsfiddle.net/ajmyZ/
//I am BAD GLOBAL FUNCTION inside var
//But I am reusable!!!
var alertBox = function () {
alert("Hey I am BAD function!!")
}
$(document).ready(function () {
//I am BAD GLOBAL var
//But I am reusable TOO!!!
var containsP = $("div p:first");
containsP.click(function () {
alert("Hi BAD var HERE!!");
});
$("p").eq(1).click(function () {
alertBox();
});
//I am the NICEST function here
//but I am NOT reusable :(
$("p").eq(2).click(function () {
alert("I am the NICEST function here!!");
});
});
I guess the simplest way to avoid clobbering the global object is just to create your own "application context". You can do that, by creating a self-invoking function which wraps your whole js-code within each file.
(function( win ) {
"use strict";
var still_global_but_only_in_this_anonymous_closure = true;
$(document).ready(function() {
// ...
// accessing the global object:
win.some_global_property = true;
});
}( this ));
Actually, you're already creating such a local context with your anonymous function you pass into .ready(). This is just the more explicit way. That self-invoking method, just calls itself with the global object as argument (where you still can explicitly access global variables). Furthermore, by invoking "use strict"; you're protected from accidently creating global variables alá "Ops_I_Forgot_The_Var_Statment = true;
The code you posted has no global variables. A variable declared inside of a function (in the case of your example, the anonymous document.ready handler) will never be global unless you make one of two mistakes:
forget the var keyword, making an implicit global
explicitly say window.myVar = ...;
On some JS code on some sites I see Javascript code such as this:
SomeName.init = (function () {
// some stuff
})();
I mean, this is not a jQuery plugin code such as this:
(function( $ ){
$.fn.myPlugin = function() {
// Do your awesome plugin stuff here
};
})( jQuery );
Then, what is it? and what is the resulting JS object?
It's a anonymous function, which doesn't leak variables to the global scope when declaring variables using var.
SomeName.init = (function () {
return 3.1415;
})();
SomeName.init is a number (3.1415), because () after the anonymous function declaration executes the function. There's no way to obtain the original function, unless defined within the anonymous function:
(function foo(){
//foo refers to this function
too = foo;
})();;
//foo is undefined
//too refers to the function, because `too` has been defined without var
The Module Pattern. And those two snippets have more in common than you think.
(function () {
// some stuff
})()
is a anonymous function that calls itself instantly. It's just a closure around the code inside to stop the variable scope becoming global.
Whatever the function returns.
(function() {
//...
})();
Is used as a way to namespace code, or declare self-executing constructors. The resulting object is whatever that self-executing function returns.
The second snippet doesn't return anything and there is no resulting JS object.