How can I call a function within a closure within a variable? - javascript

I'm a newbie in java but the code is below the explanation
This is code from a game but the problem is: Take the navigator function, I click the navigator in the game and some sort of (ajax?) goes on and it gets logged. But when I use my FireBug console I cannot send a message with the functions above the return line.
Essentially.. The only functions that ThisFunction.* shows is the ones returned at the bottom. How can I invoke the Navigator function? I've tried:
ThisFunction.a.navigator(args here);
, but it says a is undefined.. it doesn't show in the autocomplete list either.
** I removed the code because it is from a game. Thanks for the help! **

You somewhat nailed it on its head with this bit:
The only functions that ThisFunction.* shows is the ones returned at the bottom
That is the expected and purposeful functioning of the language.
Short answer: You have to return out of the closure anything that you want to be externally accessible... That could be the a variable, or it could be an api that could itself access the a variable while keeping it private from the exterior. This is called lexical scoping and it is your friend.
Example time:
var ThisFunction = (function() {
var a = { navigator: "woot" };
var b = function() {
return a;
}
});
ThisFunction.a; //a is null/undefined on the returned
ThisFunction.b; //b is defined yay
var aOUTSIDE = ThisFunction.b();
aOUTSIDE.navigator; // "woot"
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Closures
So the only things that can get at A are the things that were var'd up in the same "scope" as a. So either you return A out of the scope or you return something from inside the scope that provides an API to either get at A, or to execute some of A's internals...

Depending on what OTHERFUNCTIONSHERE is, you can access it from within one of those functions, if they close over the variable a (why such cryptic var names by the way?). Otherwise, it's out of scope.

Given that you're using Firebug, ThisFunction.%a.navigator(... args) should work (.% is a Firebug-specific extension to the language). But as noted in other answers, it's impossible from pure JavaScript.

Related

When to use an anonymous function in Nodejs?

Recently I was debugging a bit of code that one of my coworkers wrote and found something along the lines of this within a conditional, inside of a larger function.
(function(foo){
...
console.log(foo);
...
})();
So it looks like this very boiled down
function display(db, user, foo) {
if (isValid(db, user) {
(function(foo){
console.log(foo);
})();
}
...
}
Originally it didn't have (); at the end so to my understanding it wasn't even being called but to my broader question, what's the difference between that and something like below? I've seen this syntax a few times but I don't understand how above would be useful for this purpose. My understanding would reason that this just adds unnecessary complexity. Someone please enlighten me!
function display(db, user, foo) {
if (isValid(db, user) {
// without abstract function
console.log(foo);
}
...
}
Thanks :-)
With such a simple example, there is no reason to use an anonymous function like this in node.js or any other JavaScript environment when the inner function could be called directly instead.
When conducting reviews, I often will assume that any console.log (or choose-your-language logging) is accidental. If the surrounding source doesn't do anything of value itself, it is likely only intended to support a (possibly-out-of-date) console.log during development and debugging.
Because JavaScript is single-threaded, constructing an anonymous function of this sort is strictly for scoping. In the case of the original source that didn't have the execution (i.e. it was missing the ()), this is actually a way to "hide" debug code from the runtime while leaving it in-place if a step-through debug ever needed it.
When debugging, it's as easy as adding the ('isValid succeeded') to have it execute all the source inside.
(function(foo){
console.log(foo);
})( /* You're missing a parameter value here; will print 'undefined'. */ );
Sometimes you use an anonymous function to limit the scope of your code. It may come handy if you do not want to pollute the global scope with your variables. Also, it makes dependency injection for testing easier.
Consider the following examples:
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
In the above example, the a, b, and print now belongs to the window object. When your code grows it becomes difficult to keep track and avoid of name collisions. The problem becomes even more severe if you are using 3rd party libs etc.
In the example below, your code is wrapped in an anonymous function protecting the global scope. You can also pass parameters to the anonymous function
(function(localParam){
var a = 2, b = 3;
function print(x)
{
console.log('x= ', x);
}
print(a+b);
//also
console.log(localParam); // = safe way to access and global variables
})(globalParam);

jQuery - functions moving to window.function

I create a new global object and then put everything in to that new object so it doesn't interfere with anything else anyone else does. After calling the document.ready() function this gets moved to window.bf for unknown reasons. I've reduced this down to a simple example. Anyone have any ideas on what is happening?
<html>
<head>
<title>Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
debugger;
var bf = {}; // Namespace
bf.vars = [];
bf.vars['onclick'] = "";
$(document).ready(function() {
bf.noop = function() {}
bf.noop();
window.bf.noop();
});
</script>
</head>
<body>Test</body>
</html>
So I wind up with two "bf"s. One is the original global object and the second one is the window.bf object. My problem is: Originally, the global object had all of the functions and variables in it. Now the global variable has nothing except bf.vars (an array). Everything else is now in the window.bf object (including everything that was supposed to go in to the global bf.vars array yet I never asked for that to happen.
Up until last Friday (9/25/2015) this did not happen. Now it does.
Update: I just tried removing the document.ready() function. If you remove the document.ready() part - then the global bf object goes back to being a global variable. So this appears to have something to do with jQuery itself.
Before anyone asks: The reason the document.ready() is being used is because some of the functions I define make reference to locations that need to be loaded and jQuery says to use the document.ready() function in order to ensure all elements have been loaded before execution starts. The bf.noop() function is just to give an example of a function and to show that the function no longer shows up in the global bf object.
Screen capture with document.ready():
Screen capture without document.ready():
Better?
In the top-level scope of a script tag, all variables get implicitly attached to window.
The good news is, you actually don't have two bf objects, you only have one with two ways to access it.
var bf = {};
bf.foo = "bar";
document.getElementById('output').innerHTML = JSON.stringify(window.bf, undefined, 4);
<div id="output"></div>
A variable declared outside the scope of a function is bound to the global scope. Since you're declaring var bf = {} inside the script tag, its parent is the window object.
This MDN document is a good read on variables in JavaScript.
Rossipedia has both two good answers as well as leading me to find the problem. See his posts.
For unknown reasons, jQuery version 1.11.1 (I'm using v1.11.3 and thus the 1.11.1|3 in my post) has some kind of an error that was fixed in jQuery version 2.1.3.
But I also found that one of the programs I use to generate the menu for our site was generating an old function name (showIt instead of show_menu) which was causing problems also. By fixing the generated function name the problem has gone away.
This does NOT mean that the jQuery folks can go "Yeah! We don't have to fix anything!" because this is a valid error and the simple code I posted shows how to break jQuery which might mean there is some way to cause real problems with jQuery. So basically, this should be looked at by someone more in tune with jQuery to find out why the code I posted does what it does. Then they can come back and say "You idiot! You did BLAH! and you shouldn't have!" or maybe "Thanks for locating this really obscure problem that no one else in the entire world has come across or cares about." In any event - this is now a known problem. :-)

use this.argu to store arguments a good practice?

i am new to front-end developing,and now i am reading a lot of js code written by other in my company and find they will use this syntax to store the arguments :
function func1(argu1,argu2){
this.argu1 = argu1;
this.argu2 = argu2;
// other code run here....
}
for me i usually skip this and use the argument directly in my code or get a variable for the n,like this:
function func2(argu1,argu2){
alert(argu1);
alert(argu2);
var arguOne = argu1,arguSec = argu2;
// other code run here...
}
so i want want to ask why use this syntax to store an arguments?
is this a good practice ?and why?
Have i ever miss some concepts that i should know?
see the fiddle, written by the my co-worker who has been no longer a front-ender....
In your first example, func1 can be used to create objects. It is effectively a class definition (constructor). It can be used as follows:
function func1(argu1,argu2)
{
this.argu1 = argu1;
this.argu2 = argu2;
}
var instance = new func1('a', 'b');
alert(instance.argu1);
alert(instance.argu2);
Lordy lord: Instead of defining the function, and calling it at the end, try using a closure. Just keep the function definition as is, but put it in brackets:
(function new_slider (arguments)
{
//your code here
})('#new_slider',1500,150,10);
This way, the function is declared, and invoked at the same time, all functions defined within the main new_slider function will have access to the arguments. There is absolutely no reason to use this.argu1 to store these values. If anything, it creates global variables, which is considered bad practice.
Please google closures in JavaScript, they're extremely powerful

Javascript - How deeply can a variable retain its value?

Noob question here. Please see code below.
Where can I read more on this? I mean, this_variable gets 100. All subsequently defined functions seem to be able to access this variable and get it's value, but I wonder how deep does this work? I'm working on a Chrome extension and the damn thing only works with callbacks; I need to be able to access stuff within a pretty deeply nested callback and I need to be sure that what I write is reliable and will remain consistent.
(function(){
this_variable = 100;
(function(){
(function(){
(function(){
(function(){
(function(){
tadaaa = this_variable;
console.log(tadaaa); // sais 100
}());
}());
}());
}());
}());
}());
There is no limit. Though if you're nested deeply enough to worry about a limit, I would question the overall design.
As deeply as you want. The name for the concept is closures and it is the most important concept when programming advanced javascript.
As long as a variable is 'in scope' it can be accessed (presuming it's not hidden). You can nest as much as you like. See here for scoping and closure reference from MDN.
As far as you goes..
It might be slower at some point, but should still be accessible all the way through your callbacks.
Javascript uses function scoping. The rule is if a variable is set within the top level function, then all of the nested functions within the top level function have access to that variable. If a variable is declared within a nested function, then the top level function(s) will not have access to that variable.
//Immediately invoked function that scopes jQuery and outside code cannot access
$(function() {
//top-level function
function test() {
var a = true;
//nested function
function nestedTesting() {
//The nested function has access to a
console.log(a);
var b = false;
}
nestedTesting();
//The top level function does not have access to b
console.log(b);
}
test();
});
Expected Result:
true
Uncaught ReferenceError: b is not defined

Basic Javascript Function

I am trying to learn more about Javascript, I have been coding with PHP and making web application for years, I have basic knowledge of JS, most of the JS I have used has been already coded and me just plugging it in until recently, in the past years I have been able to do a lot with jQuery.
I have noticed that Stack Overflow uses jQuery more then most sites I have seen, it is beautiful all the JS functionality they have here.
So a basic question, Stack Overflow uses StackExchange in front of most of the JS code that I have seen on here. What exactly is that doing? To me I would want to say it is like a Class name but I read JS does not have classes.
Here is an example code
StackExchange.debug.log("no cache breaker for " + q);
Can you break this down for me to explain what the StackExchange, debug, log are?
I mean I can tell that log must be a function call but the others?
PS) Please don't move this to META as it is a JS question and not specific to StackOverflow
Also feel free to edit the question title and delete this line if you can think of a better title, thanks
Think of StackExchange as something much like the global jQuery function, "$" (or "jQuery"). It's just a global reference to an object that has functions and other properties.
Thus, "debug" is a property of the global "StackExchange" object, and in turn "log" is a property of the "debug" object. In this case, the "log" property references a function, which clearly is a debugging tool.
It's a debatable point whether JavaScript has "classes" or not, but it definitely has objects. (By "debatable" I mean it's a subject that fills an endless stream of blog posts and Stackoverflow questions :-)
That is, in fact, basic JavaScript. There's nothing super fancy or tricky about it.
Namespaces.
this may be relevant
How do I declare a namespace in JavaScript?
EDITED FOR CLARIFICATION
Before I say ANYTHING, please see How Classical Object-Oriented Programming Translates to Javascript. This is VERY important to understand. Now, that being said, I'll continue :)
Javascript has the unfortunate characteristic that you have to understand the run-time environment very well in order to make sense of why certain syntax is chosen over another that expresses the same thing (in theory). One of the main caveats of the run-time environment of javascript is that it is very easy to get things into the global space unintentionally. Here's two quick examples (these examples assume that you don't have any other code written):
/*
* Example 1
* This example uses 'object literal notation'.
* A link to an article about this is below the example.
* This example shows how easy it is to get into the global space just by
* not declaring variables properly.
*/
var myObj = {
myMethod: function() {
test = 'test'; // oops! now the variable test is in the global
// function space :(
// to avoid this, use var test = 'test'; to keep
// test in the scope of myMethod
}
};
Read about object literal notation.
/*
* Example 2
* This example shows how the infamous 'this' can be misused to accidentally
* get into the global space.
*/
var myConstructor = function() {
this.test = 'test';
};
var myObj1 = new myConstructor(); // 'this' will by 'myObj1'
var myObj2 = myConstructor(); // 'this' will by the global object :(
To see why Example 2 is true, see this.
One of the ways you avoid all of these headaches is by following good patterns that control access to the global scope. As some of the answers have pointed out, you can think of the StackExchange object as being used for namespacing purposes, but in reality, it's most often used to also avoid the problem listed in above example, as well prevent things such as name hoisting. In addition, you can make this 'namespacing' object also behave more like a traditional object from other classical OOP languages if you are intelligent in using closure scopes (taking advantage of the fact that all scopes in javascript are bound to functions, and functions in javascript are first-class data objects). Also, because the global space is so dangerous, it's best to "be a good DOM citizen" and only create one object in the global space that encapsulates all of your logic and data.
Joel and jeff are probably actually setting up closure scopes to do information hiding the javascript way. The below is just an example:
StackExchange = (function() { // give StackExchange it's own scope to prevent
// name hoisting and also to allow for private
// data
var version = '1.0.0'; // version only seen inside function scope
return { // return an object that will become 'StackExchange' and whose
// methods have access to this function's scope (closure)
debug: (function() {
// set up logging function that will be determined based on
// 'someCondition' (not defined in this code)
var loggingFn = (someCondition) : console.log ? alert;
return { // return obj with access to this function scope
log: function(strToLog) {
loggingFn.call(this, strToLog);
}
};
})(), // immediately execute to make object with 'debug' scope access
getVersion: function() {
return version; // this function has access to StackExchange
// scope; therefore, version will be available
}
};
})(); // immediately execute to make object with 'StackExchange' scope access
For more information, see name hoisting and scoping. Also, please read about Prototypical Inheritance in Javascript to understand patterns used to avoid global scoping problems.
This code would define the object necessary to perform the call shown in your example. As you can see, it simply defines an object containing more objects finally containing one or more functions.
var StackExchange = {
debug: {
log: function(whatever) { /* some code */ }
}
};
StackExchange.debug.log("no cache breaker for " + q);
StackExchange is a global object and debug is an another object which is a property of StackExchange object and it has a function called log.
Read more about Objects in JavaScript here.

Categories

Resources