Javascript Function Scope - javascript

This is perhaps a dumb question, but I am new to Javascript and desperate for help.
If the Javascript engine will look for global variables outside of a function, then what is the point of passing parameters to it? What do you gain?
I understand that global variables are generally frowned upon, but I still don't understand the purpose of passing variables. Does it have something to do with data encapsulation?

There's a few magic words that are used by programmers to describe different kinds of functions. Here's a few:
Re-entrant
ThreadSafe
Referentially Transparent
Idempotent
Pure
Side-Effects
You can look some of them up if you want a headache. The point is that Computer science and engineering progress has always been about reducing complexity. We have spent quite a lot of time thinking about the best way to write a function to achieve that goal. Hopefully, you can stuff tiny bits of your program into your head at a time, and understand those bits, without having to also understand the overall functioning of the entire program simultaneously, or the detailed implementation of the insides of all the other functions. A function that uses global variables can't do that very well because:
You can't guarantee that the global variables exist
You can't guarantee that the global variables are what you think they are
You can't guarantee that other parts of the program haven't modified those variables in a way you didn't expect.
You can't easily generalise to use the function multiple times on multiple sets of variables.
You can't easily verify that the function works as advertised without first setting up the function's external environment and its dependencies.
If the global variables have changed in a way you didn't expect, it's really hard to track down which part of the program is the culprit. It could be any of 500 different functions that write to that variable!
On the other hand, if you explicitly pass in all the data a function needs to operate, and explicitly return all the results:
If something goes wrong with any of those variables, it's easy to find the source of the problem
It's easier to add code to verify the "domain" of your inputs. Is it really a string? Is it over a certain length, is it under a certain length? Is it a positive number? is it whole, or fractional? All these assumptions that your code needs to operate correctly can be explicit at the start of the function, instead of just crossing your fingers and hoping nothing goes wrong.
It's easier to guess what a particular function will actually do, if its output depends only on its input.
a function's parameters are not dependant on the naming of any external variables.
And other advantages.

if you were only going to use global variables that the functions worked on then you'd always have to know the inner workings of the functions and what your global variable names had to be for them to work.
also, something like Math.abs(n) would be hard to call twice in one line if using global variables.

Functions are reusable components of your code, that executes a particular snippet on the provided variable exhibiting varying behavior.
Encapsulation comes from being Object Oriented. Functions are more for giving structure to your program.
Also, you shouldn't undermine the execution time of a method, if the variable it access exists in the context rather than being global.

If you don't need parameters to be passed to functions, then, you really don't need functions.
Functions are usually (and should be) used to provide code re-use -- use the same function on different variables. If a function accesses global variables, then every time I use it it will perform the same action. If I pass parameters, I can make it perform a different action (based on those different parameters) every time I use it.

One of the main benefits is that it keeps all the information the function needs, nearby. It becomes possible to look at just the function itself and understand what its input is, what it does, and what its output will be. If you are using global variables instead of passing arguments to the function, you’ll have to look all over your code to locate the data on which the function operates.
That’s just one benefit, of many, but an easy one to understand.

Global variables (in any language) can sometimes become stale. If there is a chance of this it is good to declare, initialise and use them locally. You have to be able to trust what you are using.
Similarly, if something/someone can update your global variables then you have to be able to trust the outcome of what will happen whenyou use them.
Global variables are not always needed by everything so why keep them hanging around?
That said, variables global to a namesapce can be useful especially if you are using something like jquery selectors and you want to cache for performance sake.

Is this really a javascript question? I haven't encountered a language that doesn't have some form of global variables yet.

Related

Is it possible to write every function as "pure function" in Google Apps Script?

I am interested in functional programming, so I decided to try this approach on the scripting environment of my Google Sheets file, and you know that the scripting language is Google Apps Script, which is basically javascript. And it even supports some (if not all) ES6 syntax.
The problem is that I cannot directly run any code, for example:
let a = 4;
Logger.log(a);
I mean, I cannot run it globally, I need to define a function with any name, and then place the code inside that function, and I can run the function, so the function runs the code inside.
So, maybe you ask, "why this behavior makes a problem writing pure functional code?" well, because, as I know, two of the most important factors about pure functions are:
1) We must not use global variables/functions inside a function, instead we must pass as parameters (and then as arguments of course).
2) defining function inside a function is often not very good idea in terms of readability and organization of the code.
So, I want to define more functions (to do some stuff), not just one "main" function, and I could not find any way, any single way to write code (as a whole) without violating at least one of the two statements above.
So, I mean, I can not write anything without making at least one non-pure function.
As a user explained in the comments:
Your 1st assumption is partially incorrect. A function must not depend on global, mutable variables, but it may depend on global constants and global pure functions. However, often you rather want to pass a function dependency as an argument to obtain a more general higher order function. Your 2nd assumption is merely opinion based.
So you could, for example, define a main function to run your code as a whole while defining functions inside the main function to achieve functional programming with Apps Script.

variable assignment vs passing directly to a function

What are the advantages/disadvantages in terms of memory management of the following?
Assigning to a variable then passing it to a function
const a = {foo: 'bar'}; // won't be reused anywhere else, for readability
myFunc(a);
Passing directly to a function
myFunc({foo: 'bar'});
The first and second code have absolutely no difference between them (unless you also need to use a later in your code) in the way the variable is passed.
The are only 2 cases in which the first might be preferred over the second.
You need to use the variable elsewhere
The variable declaration is too long and you want to split it in two lines or you are using a complex algorithm and want to give a name to each step for readability.
It depends on the implementation of the JavaScript engine. One engine might allocate memory for the variable in the first example and not allocate memory in the directly-passed example, while another implementation might be smart enough to compile the code in such a way that it makes the first example not allocate memory for a variable and thus leaves the first example behaving as the directly-passed example.
I don't know enough about the specific engines to tell you what each one does specifically. You'd have to take a look at each JS engine (or ask authors of each) to get a more conclusive answer.

Assessing variables outside scope of a function declaration

I have several functions that work together to accomplish one task. Each of those functions live in their own file. In my main file, I compose these functions to accomplish my task.
Because of this, many functions need access to the same variables. My initial approach was to declare these variables in my main file with the expectation that I could call them within my functions.
However, when I run them I get reference errors inside my functions. My current alternative includes passing these variables into each function but it doesn't seem too elegant. I also considered making a class but I run into the issue of not being able to separate the functions into different files (for organizational purposes).
// doSomething.ts
declare outerVariable
function doSomething() {
console.log(outerVariable)
}
// main
import doSomething from './doSomething.ts'
let outerVariable = 5
doSomething() // Reference Error: outerVariable is not defined
I don't think variable shadowing is an issue because I never create variables with those names in my functions.
Any idea on what's going on or a better way to structure the code?
Are there ways to accomplish what you are trying to do? Yes, but maybe that's not the way to go.
It seems you need to rethink your program structure as a whole.
First and foremost, polluting the global namespace is never a very good idea (in any programming language probably). If you are writing code using pure functional style, then yes, passing the variables as arguments to all the functions is how it's done. You can read a little about this on wikipedia (first paragraphs should give you a nice overview): https://en.wikipedia.org/wiki/Functional_programming
It also might be the case to minimize creating functions with side-effects as pointed in the comments of your question.
If the number of variables you are passing to theses functions is too large, perhaps you should consider splitting your code into smaller, more specialized functions/classes.
A single file usually contains only closely related functions or a single class.
Now, if you don't mind using objects, then you can pass to the functions one or more objects, grouping all your variables.
Also, the singleton pattern might be handy: https://addyosmani.com/resources/essentialjsdesignpatterns/book/#singletonpatternjavascript.
Try es6 export const variable = somevalue
For example, you could pass your variables into functions as arguments
Maybe it's worth considering reorganising them into a class, so they could access common class fields
It's generally good to decouple your code entities from each other, so passing them as arguments is better than declaring globals usually

When would an IIFE (JS) or protected/private/static (PHP) be used in a real situation?

I have a basic understanding of IIFEs and protected/private/static values. As I'm learning about JS, I notice IIFEs being mentioned to keep variables and functions "protected." I also notice the same thing for PHP classes, like setting a property to protected or private.
But why would any of this be done in a real situation? Wouldn't NOT ACCESSING the variables or NOT ACCESSING the class properties have the same effect?
Bonus, also why use let and const for ES6 scoping, when you just don't have to access the variable?
IIFEs are anonymous functions, which are executed immediately after they're created (unless it's inside of another block of code which needs to wait to be called). They're useful for executing code without polluting the global namespace. If you want to complete a task once, and then immediately throw away the variables created while doing said task, IIFEs should be your go to.
The const keyword is very useful for declaring a variable that is not allowed to change. For example: const pi = 3.14159;
If you are the only user of the code you write, then using this type of protection will only help readability and understanding for yourself when you come back in the future but it is, ultimately, not necessary for yourself other than following "best practices."
However, if others are using your code, then you may want (or need) to keep certain implementation private, not only to ensure operation as you have constructed but also to avoid accidental clobbering by those implementing your code.

Global variables in JS harmful? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
According to this article
http://www.mediaevent.de/javascript/globale-lokale-variablen.html
Global variables are in JS pretty dangerous.
I'm sorry that it's in German, but I'm gonna point out out the 2 main statements of the article.
The first is already in the 2nd paragraph of the head statement.
It says something like "In JS global var's are dangerous as they can get accessed by other scripts over the name" That's fine so far, as that's mostly the way why I want to use global var's don't I?
But in the article it sounds as this could happen randomly. and that's for sure not the expected behaving, is it?
But what is much more frightening me is the second last sentence. It forecasts that memory leaks will generated if a function that declares a
global variable is called multiple times.
But how could this happen if the name is still the same? how there can be multiple vars declared global with the same name?
Or is this article probably written by some one just "half-knowledge"? Or maybe just addressed to some one who isn't used to the difference between global and local at all?
Or is JS really behaving in this way?
Now a concrete example:
I want some one who logs in to my page to create a Random generated token and submit it by clicking login.
on each other button I want that this token is accessed by a different function and just submit it, so that just for a new login the key will be regenerated.
For that key I was thinking about using a global variable, which gets declared by one function and gets returned by another.
But as I will generate/regenerate the key possibly more then once, would this generate memory leaks? Or is this article I'm referring to probably just dramatizing?
If this is really the way JS is behaving, what would be a good way to make a variable accessable from different functions in my case?
The problem with globals is not memory, and it's not performance.
The problems with globals is entirely different. The problems are that they introduce global state and that scripts are not bound to a namespace.
Let's go through these problems one by one.
Having global state
This is the biggest issue here. Coding necessitates that the dependencies of a module be explicit and that communication between pieces of code is very clear.
When you have global variables which part of the code uses the variable is not nearly as clear and you can't be sure what part of the code needs it and what does not.
Let's say I have a Zoo project and I have a Bathe service that cleans an animal. Instead of passing Bathe around to each animal that needs it I have it on a global namespace and I just call Bathe(myAnimal).
Now I want to restructure my zoo and I want to know which animals need bathing because I want to optimize that. I have no way of knowing that other than going through my whole code. In order to see if my Giraffe needs bathing I have to read the entire code of the Giraffe class. If instead I passed Bathe to the constructor of Giraffe instead of using it or creating it inside giraffe (a concept called dependency injection) I can see that a Giraffe needs bathing just by reading the signature.
Now this can get way worse, what if I have state? If I'm actually changing a global variable in multiple places it becomes extremely hard to track. In a more than a few lines code base this means that you have state changing all around and no clear indication of who is changing it.
This is the main reason you should avoid globals altogether .
Scripts are not bound to a namespace
If I have two scripts on a page and my first script declares a A variable on the global namespace, the second script can access that variable. This is useful because scripts can interact this way but it's very harmful because it means that scripts can override each other's code, and communicate in an unclear way.
This of course is completely mitigated if you use a module loader like browserify or RequireJS which means your whole script only exposes two globals - require and define and then script loading is done through the loader.
This way the way independent pieces of code interact is well defined. That doesn't prevent you from creating variables on the global object, but it helps mitigating the need to do so in a uniform manner.
A note on security
Of course, anything on the client side is compromised, you can't do security or anything like that in client side JavaScript on an insecure browser (that is, you didn't prevent anything external on) because the client can just run arbitrary code on your code and read it.
There are three big problems with global variables:
name collisions
code complexity
garbage collection
Name collision
The problem with having variables in global scope is that you have less control over what else is in that scope. Your code uses a ga_ variable globally and works fine, but when you add a Google Analytics snippet that uses the same variable things unexpectedly fail and it can be quite hard to see why your shopping cart fails 2 out of 3 page loads.
If you can wrap your code in an IIFE to prevent having any variables in global scope, you should do that. Obviously there are cases where you actually want to have your code accessible globally (ex: jQuery library). In those cases, it is best practice to keep all your stuff in a single namespace (jQuery) with a relevant name.
Code complexity
It is usually a good idea to partition your code so that individual pieces have minimal interactions with each other. The more pieces interact the harder it is to make changes and to track down where bugs come from. Obviously a global variable can be accessed anywhere so when you have a problem with some code that accesses a global variable, you have to inspect every usage of that variable which can be quite a big pain. The thing to do to avoid these pains is to keep variables as local as they can be and encapsulate pieces of code so they can't interact with each other except through specific interfaces.
Memory leaks
In JavaScript you have little control over the garbage collection process. All that is guaranteed is that if you can access a variable it will not be garbage collected. This means that if you want something to be garbage collected, then you must make sure you can't access it anymore. While a global i variable which keeps a number won't be a big deal, as #Boluc Papuaccoglu mentioned when your global variable keeps more and more properties over time (an array of XHR requests for example, or array of created DOM objects), the memory consumption turn into a big deal.
All of these situations are worst case scenarios and you probably won't have issues with a small application. These recomendations have most value when you're starting to learn programming because they develop good habits and when you're working on complex applications when they save you time and money wasted on debug or difficult to do improvements.
Regarding memory leaks: Let's say you have a function, and within it you define a var, and use it for some purpose then return from the function. In this case, the memory used by the variable will be freed. However, if you relied on a global variable to do the same thing, then the memory would continue to be allocated long after your function exited. Extending the same scenario, imagine that your function adds properties to this variable with names that depend on the data the function is processing (like Order ID, Customer Name, etc.) Now, each time your function gets called, more and more properties will be appended to this variable and it will grow and grow.

Categories