Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Review articles from 1st to 21st #104

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 36 additions & 22 deletions 01 - var Scoping Refresher.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
There are a couple new ways to declare variables in ES6 that help us out with scoping. We can declare variables with `var`, which we've always used, but now we can use `let` and `const`
to declare variables too.
There are a couple of new ways to declare variables in ES6 that help us out with scoping. We can declare variables with `var`, which we've always used, but now we can use `let` and `const` to declare variables too.

These two have some attributes about them which are going to be helpful for us in creating variables but let's do a quick review to show you how `var`, `let`, and `const` are different.

Firstly, `var` variables can be **redefined** or **updated**. Let's use console.log to show the width which we can update the width to be 200, and then we'll console log the width again.
Firstly, `var` variables can be **updated** or **redefined**. Let's use `console.log` to show how a variable `width` can be set to `100` and then updated to `200`.

```js
var width = 100;
Expand All @@ -12,24 +11,32 @@ width = 200;
console.log(width); // 200
```

If you run this in your browser, you'll see we get 100, 200, which isn't a big deal. We're able to update them. You can also put a `var` in front of line 3 if you were to accidentally redeclare the variable. If you do, it won't do anything. It will work as you'd expect, but it won't yell at you for creating the same variable name twice in the same scope because `var` variables can be **updated** or **redefined**.
If you run this in your browser, you'll see we get `100` and then `200`, which isn't a big deal. We're able to update them. You can also put a `var` in front of line 3, if you were to accidentally redeclare the variable.

We also need to remember how `var` variables are scoped. **Scoping** essentially means, "Where are these variables available to me?" In the case of `var` variables, they're **function scope**, which means that they are only available inside the function that they are created in. However, if they are not declared in a function, then they are **globally scoped**, and they're available in the whole window.
```js
var width = 100;
console.log(width); // 100
var width = 200;
console.log(width); // 200
```

If I created a function and put my var width inside of it, and console logged the width, and then I were to run it? Is that going to work?
If you do, it won't do anything. It will work as you'd expect, but it won't yell at you for creating the same variable name twice in the same scope because `var` variables can be **updated** or **redefined**.

We also need to remember how `var` variables are scoped. **Scoping** essentially means, "Where are these variables available to me?". In the case of `var` variables, they're **function scoped**, which means that they are only available inside the function in which they are created. If they are not declared in a function, then they are **globally scoped**, and they're available in the whole window.

What if I were to put my variable `width` inside of a function, and `console.log` its value? Is that going to work?

```js
function setWidth() {
var width = 100;
console.log(width);
}
setWidth();
setWidth(); // 100
```

Of course, it's going to work because this `width` is available inside of this function.

Of course, it's going to work because this width is available inside of this function.

But if I also tried to console log the width after I've set the width like this?
But what if I also tried to `console.log` the variable after I've set the width like this?

```js
function setWidth() {
Expand All @@ -40,9 +47,9 @@ setWidth();
console.log(width); // error, width is not defined
```

It won't work. Why won't it work? Because **`width` is only scoped to that function**. It is a local variable to our setWidth function. It is not available outside the confines. Think of the curly brackets as gates, or function jail, and our `var` variables are in there.
It won't work. Why won't it work? Because **`width` is only scoped to the `setWidth()` function**. It is a local variable to our `setWidth` function. It is not available outside of the function's confines. Think of the curly brackets as gates, or function jail, and our `var` variables are in there.

That's important for us to know. If you do want to globally scope width, we need to declare it outside the function like so, and update it inside the function:
That's important to know. If we do want to globally scope `width`, we need to declare it outside the function like so, and update its value inside the function:

```js
var width;
Expand All @@ -54,24 +61,32 @@ setWidth();
console.log(width);
```

Generally, it's probably not what you want to do. You want to keep your variables inside of your function. If you need something outside of a function, you want to return it and store that in a variable. That's something that we need to know about function scoping. But I'm going to show you a use case where function scoping sort of comes back and bites us.
Generally, it's probably not what you want to do. You want to keep your variables inside of your functions. If you need something outside of a function, you want to return it and store that in a variable. That's something that we need to know about function scoping. But I'm going to show you a use case where function scoping sort of comes back and bites us.

Let's say we have an age variable and we have an if statement. We want to create a number of dog years. If they are greater than 12, let's calculate their ages in dog years and show "You are (however many) dog years old" in the console if they're older than 12.
Let's say we have an `age` variable and we have an `if` statement. We want to create the number of dog years for that variable. If `age` is greater than 12, let's calculate the age in dog years and show "You are (however many) dog years old" in the console.

```js
var age = 100;
if(age > 12) {
var dogYears = age * 7;
console.log(`You are ${dogYears} dog years old!`);
}

```

Just as an aside, you can see I'm using back ticks in this example, but I'm going to tell you all about this in the "Template Strings" section.
Just as an aside, you can see I'm using backticks in this example, but I'm going to tell you all about this in the "Template Strings" section.

The one thing that is a little bit strange here is that `var dogYears` is just a temporary variable, and I just needed this real quick in order to calculate something and then stick it into a `console.log` or stick it into a string or whatever. If you go to your browser console and call `dogYears`, you'll see that it's leaked outside of the if statement and it is now a global variable that lives on `window`, which isn't really what we want.
The one thing that is a little bit strange here is that `var dogYears` is just a temporary variable. I need this variable real quick in order to calculate something and then stick it into a `console.log` or stick it into a string or whatever. If you go to your browser console and call `dogYears` however, you'll see that it's leaked outside of the `if` statement and it is now a global variable that lives on `window`.

Even though this was a temporary variable that I only needed inside of one if statement, because `var` variables are **function scoped** and remember, there's no function here, it's going to be **globally scoped**. It's scoped to the entire window, which is a little bit of a pain here. That is one of the benefits to using `let` and `const`. Instead of being scoped to the function, it is **block scoped**, which is something new.
```js
var age = 100;
if(age > 12) {
var dogYears = age * 7;
console.log(`You are ${dogYears} dog years old!`);
}
console.log(dogYears); // 700
```

Even though this was a temporary variable that I only needed inside of one if statement, because `var` variables are **function scoped** and remember, there's no function here, it's going to be **globally scoped**. It's scoped to the entire window, which is a little bit of a pain here. That is one of the benefits to using `let` and `const`. Instead of being scoped to the function, they are **block scoped**, which is something new.

What is a block? Here is a great example:

Expand All @@ -85,7 +100,7 @@ if(age > 12) {
// ...
```

Any time that you see **{ curly brackets }**, that's a block. Functions are also blocks, `let` and `const` are still going to be scoped to a function, but if inside of that function or if inside of some other element that you have, **it will be scoped to the closest set of curly brackets**.
Any time that you see **{ curly brackets }**, that's a block. Functions are also blocks, which means `let` and `const` are still going to be scoped to a function. If inside of a function or if inside another block, **they will be scoped to the closest set of curly brackets**.

If I now take this dog years here and change it to `let`...

Expand All @@ -96,9 +111,8 @@ if(age > 12) {
console.log(`You are ${dogYears} dog years old!`);
}
console.log(dogYears); // error because it's scoped only to the above block

```

...and I refresh, everything works as we would want. However, if you call `dogYears` in the browser console, it says, "Dog years is not defined." Why? Because I declared it as a **`let` variable**. It is only declared inside of a block scope, now, not a global scope like `var`, a block scope, and that temporary variable has not leaked out of the block.
...and I refresh, everything works as we would want. However, if you call `dogYears` in the browser console, it says, "Dog years is not defined." Why? Because I declared it as a **`let` variable**. It is only declared inside of a block scope, and not a global scope like `var`. This means that the temporary variable has not leaked out of the block.

You can also use `const` and get the same results, which is what we will talk about in the [ES6.io](https://es6.io) video.
You can also use `const` and get the same result. The difference between the two is what we will talk about in the [ES6.io](https://es6.io) video.
36 changes: 30 additions & 6 deletions 02 - let VS const.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@ In the last post we learned all about how scoping works with [JavaScript let, co

We now know that `var` is **function scoped**, and that `let` and `const` are **block scoped**. Any time you've got a set of curly brackets, `{ }`, you've got a block scope.

Now, we need to know **you can only declare a variable inside of its scope once**.
Now, we need to know that **you can only declare a variable inside of its scope once**.

```js
const key = 'abc123';
let points = 50;
let winner = false;
```

If I try to update points by re-declaring the let variable:
If I try to update points by re-declaring the `let` variable:

```js
let points = 60;
Expand All @@ -32,6 +32,8 @@ let winner = false;
if (points > 40) {
let winner = true
}

console.log(winner); // false
```

If we type in the console, `winner` will come back as `false`. We can add a `console.log` line to prove that it runs, but why is `winner` still `false`, if we set `winner` to be `true`?
Expand All @@ -42,9 +44,20 @@ The important thing here is that these two `winner` variables are actually **two

- `let winner = true` inside the if loop is scoped to the block.


If I change our `let winner` to be `var winner`, they'll come back as `true`, because it's not inside of a function, it's not scoped to it, whereas a `let` variable is.

```js
const key = 'abc123';
let points = 50;
var winner = false;

if (points > 40) {
var winner = true
}

console.log(winner); // true
```

The other thing we need to know about it is that the difference between `let` and `const` is that `const` variables **cannot be updated**.

`let` variables are made to be updated. I may say:
Expand Down Expand Up @@ -77,7 +90,7 @@ key = abc1234;

That won't work because you cannot update a `const` variable, whereas you can update a `let` variable.

We're going to go more into examples of these and you're going to understand which one to use as we go through, but that's really all we need to know about it for now.
We're going to go more into more examples and you're going to understand which one to use as we go through, but that's really all we need to know about it for now.

One other quick thing is that sometimes people think that `const` means it's **immutable**, which means that if I have an object...

Expand All @@ -90,7 +103,7 @@ const person = {

...and if I try to update something in the `const` object by typing `person = { name: 'Wesley' }` it won't allow me to do that.

However, the properties of a `const` variable *can* change. That's because the entire object is not immutable. It just can't be re-assigned entirely.
However, the properties of a `const` variable _can_ change. That's because the entire object is not immutable. It just can't be re-assigned entirely.

The way I like to think about it with an object is that the person is me. I'm not going to ever change, my entire life, but attributes about me are going to change.

Expand All @@ -107,6 +120,17 @@ person.age = 29

That will work just fine, but I cannot ever wipe out the entire variable.

```js
const person = {
name: 'Wes',
age: 28
}
const person = {
name: 'Kait',
age: 28,
} // 'person' has already been declared
```

If you do need to freeze everything, we have something called `Object.freeze`. It's actually not part of ES6, [but you can take a look at it on MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze).

So we can use it on our object:
Expand All @@ -115,4 +139,4 @@ So we can use it on our object:
const wes = Object.freeze(person);
```

If I try to update `wes.age = 30`, it will still say `28` 👌
And if I try to update `wes.age = 30`, it will still say `28` 👌
15 changes: 7 additions & 8 deletions 03.1 - Block Scope is the new IIFE.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
## ES6 Block Scope is The new IIFE

You can probably see where `let` and `const` are going to be useful: **if you need to scope something to a block**, or **if you want to make a variable that cannot be changed** by accident or on purpose.
You can probably see where `let` and `const` are going to be useful: **if you need to scope something to a block**, or **if you want to make a variable that cannot be changed**, by accident or on purpose.

Let's take a look at a couple of more examples of when it might be useful.

The first one is replacing the **Immediately-Invoked Function Expression**, or **IIFE**. I'm not sure if you've ever heard of this before, but it was coined by [Ben Allman back in 2010]((http://benalman.com/news/2010/11/immediately-invoked-function-expression/)).
The first one is replacing the **Immediately-Invoked Function Expression**, or **IIFE**. I'm not sure if you've ever heard of this before, but it was coined by [Ben Alman back in 2010](http://benalman.com/news/2010/11/immediately-invoked-function-expression/).

An IIFE function runs itself immediately, and it creates a scope where nothing is going to leak into the parent scope. In our case, nothing is going to leak into the global scope of the window.
An IIFE function runs itself immediately, and creates a scope where nothing is going to leak into the parent scope. In our case, nothing is going to leak into the global scope of the window.

If I have a `var` variable: `var name = 'wes'`, you can call that in the console, and that's fine here. However, the window already has a `name` attribute, which is needed when you have a window opening up a another window.

`name` could also be something that some third-party JavaScript relies on in order for it to run, or again a variable used in another script. When declaring the variable globally, you may risk accidentally overwriting the previous value, which can get a little bit messy.
`name` could also be something that some third-party JavaScript relies on, or again a variable used in another script. When declaring the variable globally, you may risk accidentally overwriting the previous value, which can get a little bit messy.

The way the IIFE fixes that is that the function runs immediately and you put your variables inside of that:
The way the IIFE fixes that is that the function runs immediately and you put your variables inside of that scope:

```js
(function() {
Expand All @@ -26,7 +26,7 @@ If you try to call `name` in the console now, it's not `undefined`, it's blank b

If I needed to access our function's `name`, obviously, I'd have to do a `console.log` inside of the IIFE function, but the important thing is that it's no longer leaking into the global scope.

With `let` and `const` variables, we don't need a function for our variables to be scoped to that.
With `let` and `const` variables, we don't need a function for our variables to be scoped in this way.

Why? Because `let` and `const` use **block scope**.

Expand All @@ -42,7 +42,6 @@ If we call this in the console, we'll see `'wes'`, but if we wrap it in curly br
{
const name = 'wes';
}

```

Our `const` is going to be scoped to that block. If you try to call `name` in the console, we'll get the window's `name`, which is blank. But if we add a `console.log` to our block:
Expand All @@ -52,6 +51,6 @@ Our `const` is going to be scoped to that block. If you try to call `name` in th
const name = 'wes';
console.log(name);
}

```

... we'll get `wes` in the console. You don't IIFE stuff anymore. You're using `let` and `const` because they are going to be scoped to that block.
Loading