Code Monkey home page Code Monkey logo

week_02-day_03-advanced-js's Introduction

General Assembly Logo

Advanced JS

Objectives

  • Explain what a block is.
  • Describe the difference between global and local scope in JavaScript.
  • Identify which part(s) of JavaScript create new scope.
  • Identify which variables are accessible in various scopes.
  • Define a call back function
  • Use pass a callback function to another function and invoke it
  • Use an anonymous function with an array iteration method

Preparation

  1. Fork and clone this repository.
  2. Create a new branch, training, for your work.
  3. Checkout to the training branch.

Blocks

A Block statement is used to group code together. To create a block, we use a pair of curly braces:

{
  // Statements
}

Optionally, a block can be labeled as a visual identifier or as a target for break.

Blocks are also used with functions, conditionals and loops:

if ( /* true || false */ ) { /* within the block, body of conditional */  }
for ( /* let i = 0; ...*/ ) { /* within the block, body of loop */ }
while ( /* i < num ... */ ) { /* within the block, body of loop */ }
function ( /* arg1, arg2 */ ) { /* within the block, body of function */ }

In addition to grouping code together, blocks create a new scope for the variables defined within the block.

Scope

When we use blocks, we create a new scope for the variables defined within the block. Within a block, if we are using the ES6 let and const variables (which you should), these variables have block scope, meaning the variables defined within the block are limited in scope to the block in which it is defined:

Demo - creating block scope

const name = 'Danny'
{
  const name = 'Caleb'
}
console.log(name) // prints 'Danny'

// name = 'Caleb' is limited in scope to the block in which it is defined

You can think of scope as a collection of nested boxes. Each scope acts as a container in which variables and functions can be declared. while JavaScript is executing code within a scope, it only has access to identifiers declared in the current scope and higher scopes, the parent and global scopes.

Demo - global and local scope

Let's see some more code examples of scopes.

Remember that block scope means our different scopes are separated by blocks { }.

// I am not inside a block
if (true) {
  // i am inside a block
}
// I am not inside a block

NOT objects but blocks.

if (true) {
  // i am inside a block
}

const obj = {
  prop1: 'I am not inside a block',
  prop2: 'This is an object silly'
}

The outer most scope is the global scope and all inner scopes are considered local scopes:

// global scope
if (true) {
  // local scope
}
// global scope

Variables are accessible within the scope they are declared:

// global scope
if (true) {
  // local scope
  const x = 1  // what would happen if `var` were used instead?
  console.log(x)  // 1
  // When should we use `console` functions?
}
// global scope
console.log(x)  // ReferenceError: x is not defined

Variables are accessible to any inner scopes (child scopes):

// global scope
let x = 1

if (true) {
  // local scope
  x = 2
  console.log(x)  // 2
}
// global scope
console.log(x)  // 2

But not to the scopes above them (parent scopes):

// global scope
const x = 1

if (true) {
  // local scope
  const y = x
  console.log(y)  // 1
}
// global scope
console.log(x)  // 1
console.log(y)  // ReferenceError: y is not defined

Variables are not accessible from sibling scopes:

if (true) {
  // local scope of 1st sibling
  const a = 1
  console.log(a) // 1
}

if (true) {
  // local scope of 2nd sibling
  console.log(a) // ReferenceError: a is not defined
}

Different scopes can have variables that are declared with the same name and they do not conflict or know about each other.

// global scope
const x = 1
console.log(x)  // 1

if (true) {
  // local scope
  const x = 2
  console.log(x)  // 2
}
// global scope
console.log(x)  // 1

So that means a variable declared in the global scope is accessible by all of the scopes we create and a variable declared in a local scope is only accessible to itself and its child scopes.

Code Along - debugging variable scope

Within bin/scope-practice.js, let's get some practice creating global and nested block scopes.

// global scope
const a = 1

if (true) {
  // local scope of 1st nested if statement
  const b = 2

  if (true) {
    // local scope of 2nd nested if statement
    const c = 3
    console.log(a) // 1
    console.log(b) // 2
    console.log(c) // 3
  }

  // local scope of 1st nested if statement
  console.log(a) // 1
  console.log(b) // 2
  console.log(c) // ReferenceError: c is not defined
}

// global scope
console.log(a) // 1
console.log(b) // ReferenceError: b is not defined
console.log(c) // ReferenceError: c is not defined

Conditions are just 1 example of block scope. Loops are another example of block scope.

while (true) { // don't run this
  const a = 1
  console.log(a) // 1
}
console.log(a) // ReferenceError: a is not defined

//  For Loops still have block scope even though the syntax is different.

for (let i = 1; i < 2; i++) {
  console.log(i) // 1
}
console.log(i) // ReferenceError: i is not defined

// Functions are another example of block scope.

const anyFunction = function () {
  const a = 1
  console.log(a) // 1
}

console.log(a) // ReferenceError: a is not defined

// The scope of our parameters are within the function block as well

const print = function (a) {
  console.log(a)
}

print(1) // 1
console.log(a) // ReferenceError: a is not defined

As we have seen, utilizing scope provides great utility. We get more control over who can access and manipulate our data. We can use scope to declare a variable without polluting the global namespace. Scoping provides a way to encapsulate data and prevent other parts of our applciation from accessing variables declared within a certain scope.

When you are not familiar with the rules of scope, it will be a common source of bugs and frustration. By being aware of how scope is created, and by using scope effectively, you will write code that is more efficient, organized and less error prone.

Best Practices:

  • Don't declare or depend on global state
  • Apply the Principle of Least Privilege: Allow code to access the information and resources that are necessary for it to run, and nothing more.
    • Encapsulate code as much as possible in scope using functions and blocks
  • Never use var (prefer const over let, but never use var)
  • Never depend on scope state
  • Always pass in state as an argument when it is needed

Callbacks

Along with primitives and reference types, you can also pass in functions into other functions. A function at the end of the day is just another kind of object.

A function that is passed to another function is called a callback.

const add = function (num1, num2) {
  return num1 + num2
}

const subtract = function (num1, num2) {
  return num1 - num2
}

const doMath = function (num1, num2, operation) {
  return operation(num1, num2)
}

doMath(2,1, add) // 3
doMath(2,1, subtract) // 1

This is a very important term: What is a callback?

A callback is a function that is passed to another function.

Array Iteration Methods

We'll explore the array methods that allow us to test and transform arrays more simply and consistently, Iteration methods, and optionally at the end, we'll model some of these JavaScript Array methods as functions. Being able to use these methods correctly is our main goal.

There are two main groups of array iteration methods:

  1. Those that must process all of the array elements
  2. Those that may only process a subset of the array elements

Processing all array elements

Demo: using forEach

The forEach method iterates over all of the elements in an array. Unlike a for loop, it cannot be stopped (all elements are processed). forEach returns undefined.

From the MDN documentation:

There is no way to stop or break a forEach() loop other than by throwing an
exception. If you need such behavior, the forEach() method is the wrong
tool, use a plain loop instead. If you are testing the array elements for a
predicate and need a Boolean return value, you can use every() or some()
instead. If available, the new methods find() or findIndex() can be used for
early termination upon true predicates as well.

This means that forEach is a poor choice for an array operation that may terminate early.

Code along: using map

The map method returns a new array the same size as the existing array. The elements of the new array are set to the return value of the callback passed to map invoked with the corresponding element from the original array as its argument (e.g. newArray[i] = callback(array[i])). The array map is called upon is not mutated.

Lab: using filter

The filter method returns a new array containing elements from the original array for which the callback returns true. filter uses a predicate callback method to decide on which elements to add to the new array that it returns. The length of the new array may be 0 if the callback returned false for every element, or equal to the length of the original array, if the callback returned true for every element in the original array.

Callbacks passed to filter should be predicate functions.

Processing a subset of the array elements

Demo: using findIndex

The findIndex method returns the index of the first element in the array for which the callback returns true.

Why do we need findIndex? Why not just use indexOf?

Code along: using find

The find method returns the first element in the array for which the callback returns true.

Code along: using some

The some method return true if the callback returns true for any element of the array.

Callbacks passed to some should be predicate functions.

Lab: using every

The every method checks to see if all elements of the array meet some test. The function used for this should only return true or false. This type of function is often called a predicate.

Callbacks passed to every should be predicate functions.

Additional Resources

  1. All content is licensed under a CC­BY­NC­SA 4.0 license.
  2. All software code is licensed under GNU GPLv3. For commercial use or alternative licensing, please contact [email protected].

week_02-day_03-advanced-js's People

Contributors

micfin avatar

Watchers

James Cloos avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.