2024-10-10 01:17:08 +00:00
|
|
|
---
|
|
|
|
title: JavaScript Scoping
|
|
|
|
description: A blog post talking about how JavaScript handles scoping
|
|
|
|
date: 2024-08-11
|
|
|
|
tags:
|
|
|
|
- development
|
|
|
|
- javascript
|
|
|
|
- typescript
|
|
|
|
slug: javascript-scoping
|
|
|
|
draft: true
|
|
|
|
---
|
|
|
|
|
|
|
|
## The EventEmitter Class
|
|
|
|
|
|
|
|
The other day I was reading through the Types file of the MariaDB JavaScript
|
|
|
|
library (since its the better MySQL library for Node.js), and I noticed that
|
|
|
|
the `PoolConnection` class _actually_ extends the `EventEmitter` class from
|
|
|
|
Node.js. That in and of itself isn't that exciting, but it had me thinking
|
|
|
|
about the utility of extending that particular class, and how the scopeing of
|
|
|
|
the code used in that class would actually work.
|
|
|
|
|
|
|
|
I never put a lot of thought into it, but if you have used the `EventEmitter`
|
|
|
|
class in JavaScript at any point in your life, you know that you can attach
|
|
|
|
callbacks to events that will be run when that particular event is emitted.
|
|
|
|
|
|
|
|
```javascript
|
|
|
|
import EventEmitter from "node:events";
|
|
|
|
|
|
|
|
const em = new EventEmitter();
|
2024-11-19 02:49:38 +00:00
|
|
|
em.on("some-event", function () {
|
2024-10-10 01:17:08 +00:00
|
|
|
console.log("Something happened.");
|
|
|
|
});
|
|
|
|
|
|
|
|
em.emit("some-event");
|
|
|
|
```
|
|
|
|
|
|
|
|
When you call `em.emit("some-event")` anywhere this `EventEmitter` exists in
|
|
|
|
code, you will get a console log from inside that function. Okay, makes sense,
|
|
|
|
so what's interesting about this?
|
|
|
|
|
|
|
|
Well the scope of the callback function actually ineherits the called method's
|
|
|
|
properties and methods. This can get really interesting if you are extending
|
|
|
|
the functionality of the `EventEmitter` class - like in the MariaDB module's
|
|
|
|
`PoolConnection` class.
|
|
|
|
|
|
|
|
## Getting In-Depth with Scope
|
|
|
|
|
|
|
|
So say we had a class that extends the `EventEmitter` class and had some
|
|
|
|
methods with some state we cared about in the callback. In the MariaDB context
|
|
|
|
that could be anything that has to do with the connection pool - like maybe
|
|
|
|
how many open connections are available. We can sketch this out in a very
|
|
|
|
trivial class example in TypeScript.
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
import EventEmitter from "node:events";
|
|
|
|
|
|
|
|
class SomePool extends EventEmitter {
|
|
|
|
private freeConnections: number;
|
|
|
|
|
|
|
|
public constructor() {
|
|
|
|
super();
|
|
|
|
this.freeConnections = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
public getFreeConnectionCount(): number {
|
|
|
|
return this.freeConnections;
|
|
|
|
}
|
2024-11-19 02:49:38 +00:00
|
|
|
|
|
|
|
public function getConnection() {
|
|
|
|
this.emit("pre-connect");
|
|
|
|
|
|
|
|
if (this.freeConnections) {
|
|
|
|
// get a connection
|
|
|
|
}
|
|
|
|
}
|
2024-10-10 01:17:08 +00:00
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
So now, in any callback function* we can get the total number of free
|
|
|
|
connections in the `SomePool` class.
|
|
|
|
|
|
|
|
```typescript
|
2024-11-19 02:49:38 +00:00
|
|
|
const pool = new SomePool();
|
|
|
|
pool.on("pre-connect", function () {
|
|
|
|
if (this.freeConnections) {
|
|
|
|
this.freeConnection = this.freeConnection - 1;
|
|
|
|
}
|
|
|
|
});
|
2024-10-10 01:17:08 +00:00
|
|
|
```
|
2024-11-19 02:49:38 +00:00
|
|
|
|
|
|
|
This is a really impractical use of `EventEmitter`, but I think it does a good
|
|
|
|
job at illustrating the scope of the callback function on the `on` method and
|
|
|
|
how it can alter the state of the `SomePool` class. There is definitely a case
|
|
|
|
for when this can be super helpful and useful.
|
|
|
|
|
|
|
|
## The Arrow Function
|
|
|
|
|
|
|
|
One of the big things in JavaScript is to use this nifty little short-hand to
|
|
|
|
create a function:
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
[1, 2, 3].map((i) => i + 1);
|
|
|
|
```
|
|
|
|
|
|
|
|
This is super useful to keeping code clean and concise - but there is a huge
|
|
|
|
caveat using the arrow function over the classic function definition. When you
|
|
|
|
do an arrow function, you are not inheriting the scope of the object you are
|
|
|
|
attaching the callback to.
|
|
|
|
|
|
|
|
So in the example above, the object is the Array object, implicitly
|
|
|
|
instantiated, and having its method `map` called (which iterates over each of
|
|
|
|
the items in an Array, and does something, in this case, adding 1 to it).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|