So, there are different types of “scopes“, like global, local, closure etc. Anything with var and let doesn’t go into the global scope but some variables (without var/let) and functions will go into global scope
It gets worse
- Act as functions (duh!)
- Act as constructors (huh?)
And how do we know which is which? Well, there is no definitive way of determining that.
However, there is a convention that if the function name is camelCase, it is to be used like a function
Functions can also be used to create objects as they act as constructors
Sheesh! All this is soooo confusing. Not really! Let’s take a look at Digital Concept Visuals to understand what is happening inside the Process Map
When we do
eich = new Person(1, "Brendan");
we create an “object” from the function.
However, when we just call it as a function
let result = Person(2, "Wrongdon");
there is not object created, we are just running the function with this point to where? global dictionary
OOPS! We just polluted the global dictionary with id and name.
So how do we avoid id?
- use new when function name is upper – Person, Emp, Product
- call like regular function when its camelCase – add, getProduct, calcDiscount
All that is fine, but what if someone else calls our functions incorrectly?
Well, there are a number of ways we can can handle it.
- Pollyfill globalThis
Let's start with new.target
Yay! We got it!
Sometimes we use functions like “injectors”… ‘Point and shoot’.
If I am writing a function, I can use another function to inject properties and methods into my own object by simply calling them using .call and .apply
Sadly, Person.call does not get called with new, hence Person function rejects it.
What if we want ONLY normal calls like Person(1, “Eich”) to be rejected and not these
- new Person(1, “Eich”);
- Person.call(this, 2, “Dahl”);
- Person.apply(this, [2, “Dahl”]
globalThis to the rescue
Basically we just want to reject it if called as normal function. So what is unique about it when it’s called as global function? THIS!!!
If called as normal function this is global. So let’s just test for THAT
Yay! We’ have done it! Umm.. not really
When running in node.js, it has a global dictionary, but when running in browsers, there is no global but it’s called window
Oh ok! Let’s update it then
Oops.. wherever we execute it, we will get an error… either for global or for window.
Finally!!! We have a way of rejecting ONLY pure function call but allow new, call and apply.
So, what do we do? Polyfill!
I am not going to go into details of how to polyfill globalThis but I can point you to another article which shows how ugly it’s going to be