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
Related
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.
are there any specific disadvantages of defining a global function, as there are for defining global variables?
We are trying to downsize our custom JS file, and quite a bit of code is being used across functionalities.
Namespace collisions are one big issue. If you create a global function, and accidentally use the same name as another global function, you will overwrite that function, which may cause your application to break.
Bear in mind that all global variables are actually properties of the window object. If you accidentally overwrite a built-in property of window, you might produce some really odd glitches that can be hard to track down.
Another reason is just general cleanliness/organization. If you write a dozen functions to do operations on strings, you might want to put them all on an object stringOps, so that you've got them in one place.
The main danger with global references are that you will step on someone elses reference or vice versa. This can make testing extremely difficult as you may have introduced a large dose of non-determinism.
For instance say you define Global.PI as 3.14159 and your functions which ref that work fine, until a user loads a page with a library that defines Global.PI as 'Lemon', now your functions work not quite as expected.
The project I work on has global references due to the strucutre of our application.
To alleviate some of these issues we will attach a single object to window (window.yourObjHere) and place our global references within that object.
The only advantage to Globals are that some things simply can't be done without them. We have an eventBus that must message over seperate AngularJS applications. As the AngularJS native eventBus is per application, we have to register each application on our GLobal object in order to keep track of where messages should go etc. Whenver possible avoid using Globals but there are simply some things which can't be done without them. Just be careful and limit your Global footprint.
The disadvantages are as poeple ahve outlined (basically no namespacing meaning functions/variables can be overwritten) but you could get around this by declaring a global object which has all you need in it - and you can add things to it 'on the fly' :
GLOBAL_myObject = {
variableOne: 1,
variableTwo: "A atring",
getThisAndThat: function(p1,p2) {
//do some stuff
return p1 * p2; /or somthing
}
};
So refer to all your own variables as a property of that object:
alert(GLOBAL_myObject.variableOne);
GLOBAL_myObject.getThisAndThat(1,2);
Effectively you're just namespacing the variables.
to add more to the global GLOBAL_myObject you can just declare it ..
GLOBAL_myObject.anotherThing=1965; // what a year!
I'm working on an application framework written as an object literal and for the sake of simplicity I'd like to do two things:
Have the object available globally
Use the object name (as globally defined) for all references (vs. using this)
So, I've run some tests, done research, and am not finding any good reason NOT to take this approach. My question is - am I missing something? Perf tests actually seem to favor my method and from a logistical level I don't see any issues. Looking at other frameworks I've seen a mix, but I know that the this reference is revered by many programmers.
For reference...
A very minimal example of my approach:
var myobj = {
someVal: 'foo',
init: function(){
// Make myobj available globally
window.myobj = myobj;
// Fire off a method
myobj.doStuff();
},
doStuff: function(){
// Just print out the contents...
console.log(myobj.someVal);
}
}
myobj.init();
Note the references are all to the global, not this.
Like I said, I've seen a mix of this, I guess I just would like to know if this could cause issues in the long-run or if this a much ado about nothing.
As far as limitations go, the first thing that comes to mind is that you could only have one instance of this object. Trying to initialize a new one would wipe out the object.
Another reason for using this rather than a global variable name is that this will point to the correct object even if the name of the variable changes.
If you really want this to be a "create once" global object whose name never changes then this technique isn't technically wrong. But it won't be able to be used in any other situation. It is probably wiser to consider writing code that will be more adaptable if the requirements change (for instance if you use a library that causes a naming conflict with the chosen variable name)
Using this lets you be flexible in renaming the variable and passing it in different contexts without worrying about tracking variable names. It also will make it easy to change if naming conflicts arise.
Someone mentioned that immediate or self-executing functions have to store the whole stack. Is this true...If so what are the pros and cons of using something like the module pattern (which is based on an immediate function) vs. a plain function?
A function is inherently private, but you can return items that you want to be public, so it can handle privacy.
The main difference I see, is that you don't have global imports or the ability to make sure that the developer ( wait that's me ) uses new with the function ( or it is complicated ).
In general when trying to provide privacy and state when should one use the module pattern and when should one just use a plain function?
A second side question is does a function provide state when used with new?
Any function closure that persists because there are lasting references to variables or functions inside it occupies some amount of memory. In today's computers (even phones), this amount of memory is generally insignificant unless you're somehow repeating it thousands of times. So, using the language features to solve your design problems is generally more important than worrying about this amount of memory.
When you say "the whole stack", the calling stack for a top-level self-executing function is very small. There's really nothing else on the stack except for the one function that's being called.
A function is also an object. So, when it's used with new, it creates a new object that can have state (it's properties) if you assign values to those properties. That's one of the main ways that objects are created in javascript. You can either call a function and examine it's return value or you can use it with new and the function serves as the constructor for a new object. A given function is usually designed to be used in one way or the other, not both.
The module pattern is generally used to control which variables are public and when making them public to put them into a structured namespace that uses very few top-level global variables. It isn't really something you choose instead of self-executing functions because they don't really solve the same problem. You can read more about the module pattern here: http://www.yuiblog.com/blog/2007/06/12/module-pattern/
You can read about a number of the options here: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth and http://www.klauskomenda.com/code/javascript-programming-patterns/.
It is easier to discuss the pros/cons of a given technique in light of a specific problem that one is trying to solve or a specific design issue rather than a generic discussion of which is better when the things you've asked about are not really solving equivalent issues.
The best reference I know of for protected and private members (which can be hacked into javascript, but are not a core language feature) is this one: http://javascript.crockford.com/private.html. You are making tradeoffs when you use this method instead of the default prototype feature of the language, but you can achieve privacy if you really need it. But, you should know that javascript was not build with private or protected methods in mind so to get that level of privacy, you're using some conventions about how you write your code to get that.
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.