Categories
JavaScript

Why is Lodash Still Useful?

With the release of ES6 and later versions of JavaScript, there were lots of methods released with it, expanding the functionality of the language. For example, there are new array and string methods, as well as useful operators like the spread and rest operators.

However, JavaScript still doesn’t make utility libraries like Lodash obsolete because there are lots of useful methods that still aren’t available in JavaScript.

In this article, we’ll look at a few methods from Lodash that still makes development easier than with plain JavaScript, including the times, get, set, debounce, deburr, and keyBy methods.

_.times

The times method lets us call a function multiple times, put all the retuned results of each function call into an array, and return it.

It takes 2 arguments, which are the number of times that the function is called and the second is the function to call.

For example, we can use it as follows:

import * as _ from "lodash";
const getRandomInteger = () => Math.round(Math.random() * 100);  
let result = _.times(5, getRandomInteger);  
console.log(result);

Then we may get the following result:

[16, 83, 35, 87, 41]

_.debounce

We can use the debounce method to delay a call of a function by a specified amount of time. There’s no easy way to do this with JavaScript.

This is useful for event handling where we want to wait for something to be done and then call a function. For example, with a typeahead search, a debounce would wait until the user is finished typing before making the API call, removing unnecessary hits on your server.

For example, we can use it as follows. Given the following number input:

<input type="number" />

We can write the following JavaScript code:

import * as _ from "lodash";
const checkPositiveNumber = e => {  
  console.log(+e.target.value > 0);  
};

const numInput = document.querySelector("input[type=number]");  
numInput.addEventListener("input", _.debounce(checkPositiveNumber, 600));

The code above has the checkPositiveNumber function that checks if the value entered is positive. Then we use the debounce method, which takes the function and the delay before calling it in milliseconds.

The function returned by debouce has the same parameters and content as the original function, except that it’s delayed by the given number of milliseconds before calling it.

_.get

The get method lets us access the properties of an object in a safe way. That is, even if the path to the properties doesn’t exist, it will return undefined or a default value instead of crashing the program.

For example, given the following object:

const obj = {  
  foo: {  
    bar: { baz: { a: 3 } },  
    foo: { b: 2 },  
    baz: [1, 2, 3]  
  }  
};

We can access obj‘s property as follows:

const result = _.get(obj, "foo.bar.baz.a", 1);

The first argument is the object we want to access a property’s value. The second is the path to the property. The last argument is the default value.

We should get 3 for result.

On the other hand, if the path doesn’t exist or it’s undefined, then we get undefined or a default value returned.

For example, if we have:

const result = _.get(obj, "foo.bar.a", 1);

Then we get 1 for result.

If we don’t specify a default value as follows:

const result = _.get(obj, "foo.bar.a");

Then we get undefined.

There’s no way to safely get the value of a deeply nested property until the optional chaining operator becomes mainstream.

_.set

There’s also a set method to assign a value to a property of an object. For example, given the same object we had before:

const obj = {  
  foo: {  
    bar: { baz: { a: 3 } },  
    foo: { b: 2 },  
    baz: [1, 2, 3]  
  }  
};

We can set a value to a property by writing:

_.set(obj, "foo.bar.a", 1);

The obj object is changed in place. As we can see, it can set values for properties that don’t exist yet. The original object didn’t have foo.bar.a and it added it automatically set the value to 1.

So we get:

{  
  "foo": {  
    "bar": {  
      "baz": {  
        "a": 3  
      },  
      "a": 1  
    },  
    "foo": {  
      "b": 2  
    },  
    "baz": [  
      1,  
      2,  
      3  
    ]  
  }  
}

It even works if the nested object doesn’t exist, so if we write:

_.set(obj, "foo.foofoo.bar.a.b", 1);

We get:

{  
  "foo": {  
    "bar": {  
      "baz": {  
        "a": 3  
      }  
    },  
    "foo": {  
      "b": 2  
    },  
    "baz": [  
      1,  
      2,  
      3  
    ],  
    "foofoo": {  
      "bar": {  
        "a": {  
          "b": 1  
        }  
      }  
    }  
  }  
}

_.deburr

To remove accents from characters with strings, we can use the deburr method. It takes in a string and returns a new string with the characters that have accents replaced with the ones that don’t have them.

For example, if we have “S’il vous plaît”:

const result = _.deburr("S'il vous plaît");

Then we get that result is "S’il vous plait" . The ‘i’ no longer has the accent.

_.keyBy

The keyBy method takes an array and the property name and returns an object with the value of the property as the keys of the object.

For example, if we have the following array:

const people = [  
  { name: "Joe", age: 20 },  
  { name: "Jane", age: 18 },  
  { name: "Mary", age: 20 }  
];

Then we can use keyBy as follows:

const results = _.keyBy(people, "name");

Then results would have the following:

{  
  "Joe": {  
    "name": "Joe",  
    "age": 20  
  },  
  "Jane": {  
    "name": "Jane",  
    "age": 18  
  },  
  "Mary": {  
    "name": "Mary",  
    "age": 20  
  }  
}

Then we get the object with name 'Joe' by writing:

results['Joe']

There’s no way to do this easily with plain JavaScript without writing multiple lines of code.

Conclusion

Lodash has many useful functions that don’t have an equivalent that are as easy to use as these methods.

There’s the times method to call a function multiple times in one line. The debounce function returns a new function with the same signature and code as the original but it’s delayed by the given amount of milliseconds before it’s called.

For accessing and setting object properties and values safely, there are the get and set methods that don’t crash when we access property paths that don’t exist or has value undefined.

Then there’s the deburr method to replace accented characters with the non-accented versions of these characters.

Finally, there’s keyBy method to get massage an array into an object that has the given property’s value of each entry as the keys and the entry with the given property’s name’s values as the value of those keys.

Categories
JavaScript

What are Rxjs Schedulers?

Schedulers are entities that control when a subscription starts and when notifications are delivered. It has 3 components:

  • data structure — It knows how to store and queue tasks based on priority or other criteria.
  • execution context — denotes where and when tasks are executed. It can be immediate or deferred until later.
  • virtual clock — tasks are run relative to the time denoted by the now() getter method on the scheduler.

Defining a Scheduler

We can define a basic scheduler as follows:

import { of, asyncScheduler } from "rxjs";  
import { observeOn } from "rxjs/operators";
of(1, 2, 3)  
  .pipe(observeOn(asyncScheduler))  
  .subscribe(val => console.log(val));

The code turns our synchronous Observable into an asynchronous Observable by using the asyncScheduler .

We’ll notice the difference if we compare the output of the synchronous example below:

import { of, asyncScheduler } from "rxjs";  
import { observeOn } from "rxjs/operators";
const observable = of(1, 2, 3);
console.log("before sync subscribe");  
observable.subscribe({  
  next(x) {  
    console.log(`got sync value ${x}`);  
  },  
  error(err) {  
    console.error(`something wrong occurred: ${err}`);  
  },  
  complete() {  
    console.log("done");  
  }  
});  
console.log("after sync subscribe");

And the asynchronous example:

import { of, asyncScheduler } from "rxjs";  
import { observeOn } from "rxjs/operators";
const observable = of(1, 2, 3);
console.log("before async subscribe");  
observable.pipe(observeOn(asyncScheduler)).subscribe({  
  next(x) {  
    console.log(`got async value ${x}`);  
  },  
  error(err) {  
    console.error(`something wrong occurred: ${err}`);  
  },  
  complete() {  
    console.log("done");  
  }  
});  
console.log("after async subscribe");

We see that the synchronous example outputs:

before sync subscribe  
got sync value 1  
got sync value 2  
got sync value 3  
done  
after sync subscribe

The asynchronous example with the asyncScheduler gets us the following output:

before async subscribe  
after async subscribe  
got async value 1  
got async value 2  
got async value 3  
done

As we can see, the asyncScheduler defers the execution of the Observable until after the synchronous code is run.

The async Scheduler operates with a setTimeout or setInterval. Even if the delay is zero it still runs on setTimeout or setInterval. It’ll run in the next event loop iteration.

The asyncScheduler has a schedule() method that takes a delay argument, which refers to the quantity of time relative to the Scheduler’s own internal clock. The internal clock doesn’t have anything to do with the actual clock time. Temporal operations are dictated by the Scheduler’s clock, not the real clock.

This is useful for testing since we can easily fake the time for testing while the tasks are run asynchronously.

Scheduler Types

In addition to the asyncScheduler , there’re other types of Schedulers available in RxJS:

  • null — notifications are delivered synchronously and recursively. Useful for constant time or tail-recursive operations
  • queueScheduler — schedules on a queue in the current event frame. Useful for iteration.
  • asapScheduler — schedules on the microtask queue, which is the same one used for promises
  • asyncScheduler — used for time-based operations. Works are scheduled with setInterval
  • animationFrameScheduler — Schedule tasks to run just before the next browser content repaint. It can be used to smooth browser animations

Using Schedulers

The following functions take a scheduler argument:

  • bindCallback
  • bindNodeCallback
  • combineLatest
  • concat
  • empty
  • from
  • fromPromise
  • interval
  • merge
  • of
  • range
  • throw
  • timer

We’re already using Schedulers without specifying it explicitly. RxJS will pick a default scheduler by finding one that introduces the least amount of concurrency and does the job.

For example, for timed operations, async is used, for simpler ones that are emit a finite amount of messages, null or undefined are used.

Some operators also take a Scheduler argument. They include time related ones like bufferTime, debounceTime, delay, auditTime, sampleTime, throttleTime, timeInterval, timeout, timeoutWith, windowTime .

Other instance operators like cache, combineLatest, concat, expand, merge, publishReplay, startWith also take a Scheduler argument.

With Schedulers, we can control when data are emitted by Observables. There’re different kinds of Schedulers which RxJS will pick automatically based on the principle of creating the least concurrency to do the job.

Schedulers run tasks according to their own clock. It has nothing to do with the real world’s clock.

Many operators allow us to set a Scheduler to meet our needs.

Categories
Angular

How to Use Angular Material to Build an Appealing UI

Material Design is a design language developed and released by Google in 2014. It dictates a set of rules that all apps using Material Design must follow. Since Google also develops the Angular framework, Material Design support within the Angular framework is first-class.

If you are familiar with Angular, getting started with Angular Material is easy and the documentation is very good. In this piece, I will walk you through the steps required to get started with Angular Material.


Installing the Framework

To get started, you need the latest version of Node.js and Angular CLI. You can install Node.js by following the instructions here.

Angular CLI can be installed by running npm i -g@angular/cli.

Once installed, run npm install --save @angular/material @angular/cdk @angular/animations to install Angular Material with the Angular Animations library, which is necessary for the Angular Material’s widget’s animations.


Create Your Angular Application

To create a new Angular app, run ng new yourAppName, where yourAppName can be replaced with your preferred name for your app.

When running ng new, use the scss option so that you can use CSS and SCSS code for styling. Also, make sure to select yes if it asks you if you want to include a routing module.

If you want to include the Roboto font and Material icons, add:

<link href="https://fonts.googleapis.com/css?family=Roboto&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

Type caption for embed (optional)

to index.html to use them globally.

In this example, I will create an app with a login form, forms for updating user info and passwords, and a table for displaying personal information.

First, we have to add the dependencies to app.module.ts , like so:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
  MatButtonModule,
  MatCheckboxModule,
  MatInputModule,
  MatMenuModule,
  MatSidenavModule,
  MatToolbarModule,
  MatTableModule,
  MatDialogModule,
  MAT_DIALOG_DEFAULT_OPTIONS,
  MatDatepickerModule,
  MatSelectModule,
  MatCardModule
} from '@angular/material';
import { MatFormFieldModule } from '@angular/material/form-field';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { StoreModule } from '@ngrx/store';
import { FormsModule } from '@angular/forms';
import { TopBarComponent } from './top-bar/top-bar.component';
import { HomePageComponent } from './home-page/home-page.component';
import { LoginPageComponent } from './login-page/login-page.component';
import { SignUpPageComponent } from './sign-up-page/sign-up-page.component';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
@NgModule({
  declarations: [
    AppComponent,
    TopBarComponent,
    HomePageComponent,
    LoginPageComponent,
    SignUpPageComponent,
    PasswordResetRequestPageComponent,
    PasswordResetPageComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatButtonModule,
    MatCheckboxModule,
    MatFormFieldModule,
    MatInputModule,
    MatMenuModule,
    MatSidenavModule,
    MatToolbarModule,
    MatTableModule,
    FormsModule,
    MatSelectModule
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Type caption for embed (optional)

The code above incorporates the Angular Material dependencies into our main app module, which is necessary for them to be recognized by Angular when the custom elements are used in the templates.

In style.scss , add @import "~@angular/material/prebuilt-themes/indigo-pink.css"; to import the Angular Material styling.

In addition, you can add:

body {
  font-family: "Roboto", sans-serif;
  margin: 0;
}
form {
  mat-form-field {
    width: 95vw;
    margin: 0 auto;
  }
}
.center {
  text-align: center;
}

into styles.css to use the Roboto font and make the form fit the width of your screen.


Building the UI

Create the skeleton code for the login page by running ng g component loginPage. It will be calledlogin-page.component. The template will be called login-page.component.html and the component is called login-page.component.ts.

In login-page.component.ts add:

<div class="center">
  <h1>Log In</h1>
</div>
<form #loginForm='ngForm'>
  <mat-form-field>
    <input matInput placeholder="Username" required #userName='ngModel' name='userName' [(ngModel)]='loginData.userName'>
    <mat-error *ngIf="userName.invalid && (userName.dirty || userName.touched)">
      <div *ngIf="userName.errors.required">Username is required.
      </div>
    </mat-error>
 </mat-form-field>
  <br>
  <mat-form-field>
    <input matInput placeholder="Password" type='password' required #password='ngModel' name='password' [(ngModel)]='loginData.password'>
    <mat-error *ngIf="password.invalid && (password.dirty || password.touched)">
    <div *ngIf="password.errors.required">Password is required</div
    </mat-error>
  </mat-form-field>
  <br>
  <button mat-raised-button type='submit'>Log In</button>
  <a mat-raised-button>Reset Password</a>
</form>

Type caption for embed (optional)

This creates a form with Angular Material styled inputs, along with Material styled form validation messages.

Now, create a new component by running ng g component settingsPage. This will create a file called settings-page.component.html where you can add the following:

<table mat-table [dataSource]="elements" class="mat-elevation-z8" *ngIf="elements.length > 0">
  <ng-container matColumnDef="key">
    <th mat-header-cell *matHeaderCellDef>
      <h3>Account Data</h3>
    </th>
    <td mat-cell *matCellDef="let element">
      {{element.key | capitalize}}
    </td>
  </ng-container>
  <ng-container matColumnDef="value">
    <th mat-header-cell *matHeaderCellDef></th>
    <td mat-cell *matCellDef="let element">
     {{element.value}}
    </td>
  </ng-container>
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

Type caption for embed (optional)

In settings-page.component.ts, add:

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-settings-page',
  templateUrl: './settings-page.component.html',
  styleUrls: ['./settings-page.component.scss']
})
export class SettingsPageComponent implements OnInit {
  elements = [
    {key: 'name', value: 'John Au-Yeung'},
    {key: 'screen name', value: 'AuMayeung'},
  ];
  displayedColumns: string[] = ['key', 'value'];
}

This will display a table on the page. displayedColumns are the columns of the table. Angular Material will loop through the entries in the [dataSource] attribute and display them.

In app-routing.module.ts, add the following:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LoginPageComponent } from './login-page/login-page.component';
import { SettingsPageComponent } from './settings-page/settings-page.component';
const routes: Routes = [
  { path: 'login', component: LoginPageComponent },
  { path: 'settings', component: SettingsPageComponent },
];
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

This will allow you to access the pages you created by entering the URLs.


Conclusion

Once completed, we end up with the login and settings pages.

Categories
JavaScript JavaScript Basics

Where’s the Sleep Function in JavaScript?

If we try to search for the sleep function in JavaScript, we won’t find it. However, we can easily make one with existing functions.

setTimeout Function

There’s a setTimeout function that lets us run code after a specified number of milliseconds. We can use it to create our own sleep function.

Like most time-sensitive JavaScript code, it’s going to be asynchronous since this won’t hold up the main thread running our program.

We can create a function that runs code after a specified amount of time by writing:

const runLater = (delay) => {  
  setTimeout(() => {  
    console.log('bar');  
  }, delay)  
}

The runLater function will show the string 'bar' when we pass in the delay by in number of milliseconds.

If we run:

console.log('foo')  
runLater(100);  
console.log('baz')

We’ll see that we get:

foo  
baz  
bar

This is because the synchronous code, which are the first and last lines, are run first. The runLater(100) is queued up to be run in the next iteration of the event loop between the time when the first and last lines are run.

Then in the next iteration of the event loop, the code in the setTimeout callback runs, which will log 'baz' .

This means that if we want to run code in callbacks sequentially, we have to nest the callbacks. And too many callbacks create callback hell.

Promises

Therefore, the best way to run asynchronous JavaScript code sequentially is to use promises. We can create a promise with the setTimeout function by using the Promise constructor.

We can write the sleep function as follows:

const sleep = (delay) => {  
  return new Promise(resolve => {  
    setTimeout(resolve, delay)  
  });  
}

The sleep function returns a promise which resolves after the setTimeout callback, which is the resolve function is called after delay milliseconds.

A promise is asynchronous like the setTimeout callback. The good thing about it is that we can run them sequentially as they’re fulfilled.

Fulfilled means that the resolve method in the callback above is called. A promise can also be rejected with the reject function when an error occurs.

Using promises let us chain asynchronous code and run them sequentially.

We can do this cleanly with async functions. To define an async function, we use the async and await keywords as follows:

(async ()=>{  
  console.log('foo');  
  await sleep(2000);  
  console.log('bar');  
})();

If we run the code above, we should see that 'foo' is logged, then 2 seconds after that 'bar' is logged.

This will let us up time delayed code without hanging our app.

The number 2000 in the argument is in milliseconds, so it’ll wait 2 seconds before running the next line.

await tells the browser to hold off on executing the next line until the await line is resolved. We can put await in front of any promise to indicate that we should wait for the promise to resolve before continuing.

We can keep repeating this:

(async () => {  
  console.log('foo');  
  await sleep(2000);  
  console.log('bar');  
  await sleep(2000);  
  console.log('a');  
  await sleep(2000);  
  console.log('b');  
})();

But it gets repetitive. Fortunately, we can use loops to eliminate this repetition.

For-Await-Of Loop

We have the for-await-of loop which loops through iterable objects like arrays and array-like objects whether they’re synchronous or asynchronous.

To do this, we can write:

(async () => {  
  const arr = ['foo', 'bar', 'a', 'b'];  
  for await (let a of arr) {  
    console.log(a);  
    await sleep(2000);  
  }  
})();

The code above is much cleaner and it doesn’t matter how many things we want to loop through.

It’s important that we actually have promise code inside our async functions whether we want to use loops or not.

We can also return a promise from an async function, so we can write:

(async () => {  
  const arr = ['foo', 'bar', 'a', 'b'];  
  for await (let a of arr) {  
    console.log(a);  
    await sleep(2000);  
  }  
  return sleep(2000);  
})();

to return the sleep(2000) promise.

Also, we can give it a name and use it in other async functions as follows:

const foo = async () => {  
  const arr = ['foo', 'bar', 'a', 'b'];  
  for await (let a of arr) {  
    console.log(a);  
    await sleep(2000);  
  }  
  return sleep(2000);  
};

(async () => {  
  await foo();  
  console.log('c');  
})();

This shows that async functions are promises.

Conclusion

In JavaScript, there’s no sleep function like in other languages. However, we can make our own easily.

With promises, we can solve timing issues easily. It makes time-delayed code execution clean and readable. We can write time-delayed JavaScript code by using the setTimeout function.

The async and await syntax makes reading and writing the code a breeze.

Finally, we can call async functions in other async functions since these types of functions return promises only.

Categories
JavaScript JavaScript Basics

What’s so Special About JavaScript Functions?

In JavaScript, there are multiple ways to declare a function. One way is to declare it with the function keyword. The other way is to declare it as an arrow function.

In fact, there are two ways to declare a function with the function keyword. One way is using function declarations, which are also called function statements, and the other is to use function expressions.

In JavaScript, functions are first-class, which means that they’re objects we can define on the fly.


Function Declarations

Function declarations, also called function statements, are the way we define a function — with the function keyword followed by the name of the function.

For example, we can write the following to define a function with a function declaration:

function foo(){  
  return 'foo';  
}

A function declaration is stored in memory prior to executing the program. This means we can reference it anywhere in our code, even before it’s declared. Storing a variable in memory prior to executing the program is called “hoisting” in JavaScript.

For example, if we write the following:

console.log(foo());

function foo() {  
  return 'foo'  
}

console.log(foo());

We get foo logged from both function calls.


Function Expressions

Function expressions are functions stored as a value of a variable.

For example, to define a function as a function expression, we write:

const foo = function() {  
  return 'foo'  
}

Unless they’re function declarations or statements, function expressions aren’t stored in memory before the program runs. The function is defined in run-time, so we can only reference them after they’re declared.

For example, if write the follwing:

console.log(foo());

const foo = function() {  
  return 'foo'  
}

console.log(foo());

We’ll get the following error: Uncaught ReferenceError: Cannot access ‘foo’ before initialization’.

In the code above, we have the variable declaration when the program initially runs, but we don’t have the function assigned to it yet, so we can’t access it. Also, anything defined with the let , or const keywords can’t be used with those variables or constants before it’s defined, which also prevents it from being run.


When Should We Use Function Declarations or Expressions?

It depends on personal style. Function declarations are more convenient — they’re available in any part of the script — while function expressions let us assign a function to a variable and reference the variable in various ways, like the calling methods it has.

First-Class Functions

As we see in the function expression example, we can assign a function to a variable in JavaScript. The term for this is a first-class function. First-class functions are functions defined on the fly as the program runs.

This is because in JavaScript, functions are objects just like everything else. Functions have their own methods and other properties and can be used just like objects.

For example, all functions have the toString method to convert them to a string with the code that defines the function.

Other methods in a function would be methods that call a function with a different this value, like bind , call , and apply.

We can use the toString method by writing the following code:

function foo() {  
  return 'foo'  
}

console.log(foo.toString());

Then we get the following from the console.log:

function foo() {  
  return 'foo'  
}

The bind, call, and apply methods are similar. They all take an object for the this keyword in the function as the first argument. bind and call take a comma-separated list of arguments for the other arguments and apply takes an array of arguments as the second argument.

For example, we can change the value of this in a function with the call method by writing the following code:

let obj = {  
  firstName: 'Joe',  
  lastName: 'Smith'  
}

let person  = {  
  firstName: 'Jane',  
  lastName: 'Smith',  
  getFullName()  {  
    return `${this.firstName} ${this.lastName}`  
  }  
}

console.log(person.getFullName());  
console.log(person.getFullName.call(obj));

The first example would be the same except that we change call to apply, since we didn’t pass in the second or subsequent arguments:

let obj = {  
  firstName: 'Joe',  
  lastName: 'Smith'  
}

let person  = {  
  firstName: 'Jane',  
  lastName: 'Smith',  
  getFullName()  {  
    return `${this.firstName} ${this.lastName}`  
  }  
}

console.log(person.getFullName());  
console.log(person.getFullName.apply(obj));

Then we get Jane Smith for the first console.log, since we haven’t changed the value with apply yet, but we changed the value of this to obj with the apply method in the second console.log so that we get Joe Smith.

We can call bind with an object passed in, as in the following code:

let person = {  
  firstName: 'Jane',  
  lastName: 'Smith',  
  getName() {  
    return `${this.firstName} ${this.lastName}`  
  }  
}

const joe = {  
  firstName: 'Joe',  
  lastName: 'Smith'  
}

console.log(person.getName.bind(joe)());

Then we get 'Joe Smith' since we passed in the joe object into the first argument of the bind method, which sets the this object inside the getName method to the joe object.

In JavaScript, there are two ways to declare a function with the function keyword. One way is using function declarations, which are also called function statements, and the other is to use function expressions.

Function declarations are defining a function with the function keyword followed by the name of the function. They are available anywhere in the program.

Function expressions are functions assigned to variables. They’re only available after they’re declared and assigned to the variable.

In JavaScript, functions are first-class, which means that they’re objects that we can define on the fly.

With these features in mind, we can use in ways that are different from languages like Java, where functions can only be inside classes.