Purposefully creating global variables is bad style, but accidentally creating global variables can be a downright disaster
Effect JavaScript : 68 Specific Ways to Harness the Power of JavaScript
-
- More local less global
- I am talking about local vs global scope. As a javaScript learner and after reading several books and blog notes I have come to the realization that global is BAD and local is Good. okay I am kidding. However if you are working with variables, for instance, try to prevent populating the global scope/object with your variables, since this could/may overwrite existing properties of the global object. Most of the time, when I create variables, I need them only for a certain function and nothing else. If that is your case as well, just may it local dude or dudette.
- For exampleee… instead of
- More local less global
[sourcecode lang=”javascript”]
///NO NO!!! here you are setting window.name = "Comfort Ajala". Even if you did not intend to do so.
function(){
name = "Comfort Ajala"
console.log(name)
return
}
[/sourcecode]
Do this
-
[sourcecode lang=”javascript”]
//window.name = undefined (or already set by the environment) !GOOOD
function(){
var name = "Comfort Ajala"
console.log(name)
return
}
//window.name = undefined !GOOD
[/sourcecode]
-
- And my favvvvvvvvee!!! Closures
- The only reason why I enjoy using them is because it took me 2 years to finally grasp what they are used for and how they are used….. geez.. I am slow. So closures, as simply as I can descripbe them, are “inner functions” that can access variables living in the outer scope /parent function. I may piss off some js gurus by my weak definition but YOLO (do they use these anymore though 🤦🏿♀️🤦🏿♀️🤦🏿♀️). This is also a nice way to reuse variables, in my experience (humble), without the need to populate intentionally or unintentionally the global space e.g. For instance..
- And my favvvvvvvvee!!! Closures
[sourcecode lang=”javascript”]
function makeaNigerianMeal(recipeName){
//below is the closure
return function printNigerianRecipeIngredients(…listofingredients){
var ingred, title, message = "", header, content //manual hoisting.. i think
title = `You are making ${recipeName}. The ingredients are `
for(ingred in listofingredients) {
message += listofingredients[ingred] + "\n"
}
header = document.createElement("h1"); header.innerHTML = title
content = document.createElement("p"); content.innerHTML = message
document.body.append(header)
document.body.append(content)
}
}
var d = makeaNigerianMeal("EBA")
d("Igbo Garri", "Hot Water")
var e = makeaNigerianMeal("MOI MOI")
e("Beans", "Tomato", "Tatashe", "Maggi", "Onions")
[/sourcecode]
-
-
-
- Even after you have called the outer function and stored the “inner function” in the variable d or e, the inner function can still access the out function’s variables …. awesome right **in my geek voice👩🏿💻**
- As defined in the book “Functions that keep track of variables from their containing scopes are known as closures.”
- Also, since closures store references to the variables in the outer scope, they can also manipulate their values….. cool but scary…
-
- Variable Hoisting
- “sighs in alien”
- Hard for me to explain because I am yet to fully understand it, BUTTTT (wait there’s more..!), if you define a variable in let’s say a for loop so..
-
[sourcecode lang=”javascript”]
function printNameNTimes(name, N){
for(var i = 0; i < N; i++){
console.log(name)
}
console.log(i)
}
printNameNTimes("Comfort", 5) //should print name 5 times
[/sourcecode]
-
-
-
- 2 years ago, I would have assumed that var i were undefined outside the scope “context” of the for loop. But… nope. The console (last 1) would print 5. weeetttttt..
- This is because of the aforementioned term HOISTING… basically all variables in a function are “hoisted” = placed/declared at the beginning of the function like this:
- 2 years ago, I would have assumed that var i were undefined outside the scope “context” of the for loop. But… nope. The console (last 1) would print 5. weeetttttt..
-
-
[sourcecode lang=”javascript”]
function printNameNTimes(name, N){
var i; //hoisted
for( i = 0; i < N; i++){
console.log(name)
}
console.log(i)
}
printNameNTimes("Comfort", 5)
[/sourcecode]
This is why “i” is still accessible any where within the function
-
-
-
- This does not apply to try and catch block scopes…. when you define a variable or update an already existing variable in the catch scope, outside of the scope it remains undefined or unaltered like so..
-
-
[sourcecode lang=”javascript”]
function tryCatch(){
var name = "Comfort Ajala";
try{
throw "exception"
}
catch(name){
name = "Tina Tery"
}
console.log(name)
}
tryCatch() //prints Comfort AJala; undefined
[/sourcecode]
- 21:51:38 04/28/2018 – UPDATE
-
- THIS
- The scope of “this” is always connected to the nearest enclosing function or in my words “parent function”
- For instance
- The scope of “this” is always connected to the nearest enclosing function or in my words “parent function”
- THIS
[sourcecode lang=”javascript”]
var person = {
trackID:0,
children:[{id:1, name:"me"}, {id:0, name:"you"}],
updateLast:function(old, newchild){
‘use strict’
this.children.map(function(child){
if(this.trackID == child.id)return newchild
else return old
}) // the reciever for the map method is "this.children", which has no property "trackID". so this.trackID will return undefined
}
}
person.updateLast({id:0, name:"you"}, {id:0, name:"you and me"})
[/sourcecode]
-
-
-
- Solution –> create a variable “self” in the outer/parent function or add “this” as a second argument to the map method
-
-
[sourcecode lang=”javascript”]
var person = {
trackID:0,
children:[{id:1, name:"me"}, {id:0, name:"you"}],
updateLast:function(old, newchild){
‘use strict’
this.children.map(function(child){
if(this.trackID == child.id)return newchild
else return old
}, this) //the reciever is updated by the second argument which is not "this.children" but the reciever of the function/method updateLast, which is "person". Person has property "trackID" –> no ERRORS YEPPIE!
}
}
person.updateLast({id:0, name:"you"}, {id:0, name:"you and me"})
//or
var person = {
trackID:0,
children:[{id:1, name:"me"}, {id:0, name:"you"}],
updateLast:function(old, newchild){
‘use strict’
var self = this
this.children.map(function(child){
if(self.trackID == child.id)return newchild
else return old
}) //the reciever is updated by the second argument which is not "this.children" but the reciever of the function/method updateLast, which is "person". Person has property "trackID" –> no ERRORS YEPPIE!
}
}
person.updateLast({id:0, name:"you"}, {id:0, name:"you and me"})
[/sourcecode]