Geek Culture
Published in

Geek Culture

Scope and Closure in Javascript

…and how to solve “Calculating With Functions” on Codewars

Ahhh, scope and closures: 2 favorite tech interview questions that trip up devs of all ages!

Let’s talk scope. What is it?

Scope is access. That’s the easiest way to think about it. It allows you, as a developer, to limit access to certain variables to specific contexts. It has two benefits:

  • security — variables that are not accessible from outside the specified scope won’t accidentally get changed later on
  • naming — allows you to use the same variable name in different scopes (you know this is helpful if you’ve used let i = 0 in separate for loops in the same function 🙋‍♀️)

Scope is often discussed in the context of functions, but I found it helpful to first think about it in the context of a nested object (functions are JS objects anyway…)

Here’s an example of an object with several layers:

a JavasScript object called “baked alaska” used to illustrate an example of scope in a nested object
Is anyone surprised I’m using a food example? Didn’t think so.

Here we have the wildly under-appreciated Baked Alaska, and it has several layers. If I wanted to know what ice cream is under the meringue, I couldn’t just write bakedAlaska.iceCream — I would get undefined. I would have to write bakedAlaska.innerLayer.iceCream to get to the array of ice creams. That’s because curly braces make their own scope. So the iceCream array is not defined in the direct scope of bakedAlaska. It’s defined inside the scope of innerLayer.

Types of Scope

Global Scope — this is outside of any functions or curly braces. If a variable is defined in the global scope, it can then be used anywhere in your code (including functions, objects, etc.) It’s not encouraged to declare variables in the global scope because of the reasons listed above.

Local Scope — when variables are only accessible within a specific context (like a function, or in curly braces)

  • Function Scope — a type of local scope. Variables declared inside of a function cannot be accessed outside of that function.
function sayMyName(){
let myName = "Julia"
console.log(myName) // "Julia"
}
console.log(myName) // undefined
  • Block Scope — a type of local scope, and a subset of function scope. Variables declared inside of curly braces are not accessible outside of those braces (just like in the function above.)

You promised to talk about closure…

So I did. Here’s MDN’s definition, and then we’ll unpack it:

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

“In other words, a closure gives you access to an outer function’s scope from an inner function.” Let’s see this in action using a similar example to the one above:

demonstration of closure with a contrived “greet” example

As you can hopefully see, even though the outer function was invoked on line 14 and has essentially “come and gone,” the inner greet function still has access to the variable myName whenever it is later invoked. Let’s put this to work on a less contrived example.

Solving the “Calculating With Functions” problem using closure

I came across this question only a month or two into my journey as a programmer. My brain melted while trying to come up with a solution, and the question sat marinating in the back of my head for months. Recently, after re-visiting the subject of closure, I realized that was the piece I was missing.

The instructions are to create functions that when called in the example way below, will return the correct answer.

e.g. seven(plus(five())); // must return 12
four(times(nine())); // must return 36

Here are some additional stipulations:

  • There must be a function for each number from 0 (“zero”) to 9 (“nine”)
  • There must be a function for each of the following mathematical operations: plus, minus, times, dividedBy (divided_by in Ruby and Python)
  • Each calculation consist of exactly one operation and two numbers
  • The most outer function represents the left operand, the most inner function represents the right operand
  • Division should be integer division. For example, this should return 2, not 2.666666...:

My first thought was that I’d have to work from inside out, since each function would have to wait for its received function to resolve before completing execution. (See my post on call stacks if that doesn’t make sense!)

With that in mind, I started by thinking about the number functions. My thought was that the number function could either be on the outside, taking in an operator function as an argument like this: seven(some operator function here), OR it could be on the inside, receiving nothing, but returning a number: the five() of seven(times(five())). So that’s exactly what I did:

the “seven” function with conditional statements

Each number function must be able to accept a function as an argument, since an operator function might be called inside, like in the example: seven(plus(five())). If you’re familiar with ternary expressions, you could also write the function out like this:

function seven(fn) {return fn ? fn(7) : 7}

I used similar logic for the operations functions. They would need to be able to accept just one number function as an argument plus(five()). The part where I was getting stumped previously was how those operations functions would get access to both the outer number and the inner number.

Here’s where the beauty of closures comes in.

a code snippet of the “plus” function written out, with comments explaining each piece

I’m going to repeat the logic that’s written in the comments of the snippet above.

  • The first thing we do is accept an argument (x). In this example, that’s the return value of five(), i.e. 5.
  • Then we define an inner function that utilizes the value of x inside of it and accepts an argument of a number. Because the inner function has access to the outer function’s scope at the time of its definition, it will be able to use the value of x even after the outer function is long gone. Closure coming in clutch.
  • Then the outer function returns a reference to the inner function.

So now that we have all the pieces to the seven(plus(five())) expression, let’s walk through each step, replacing each function with the return values as they get resolved.

  1. seven(plus(five())) gets called.
  2. The innermost function, five()gets evaluated first. Based on our conditional statement from before, we see that this will just return the number 5.
  3. Now we move out to plus(5). Based on our code snippet, we see that x is assigned the value of 5 that our inner function add will have access to, and return a reference to the add function.
  4. Then we move out to seven(add). Based on the same function as before, we see that this time a function was, indeed passed in. Therefore, the return value is the function add invoked, with the number 7 passed in.
  5. Finally, add executes using the remembered value of 5 from its outer scope, and the passed in value of 7, for a return value of 12. 🤯

One of my instructors mentioned that a good way to picture closure was to imagine that your inner function has access to some variables “inside a backpack,” which I thought was a really charming and helpful way to think about it. So we’ll close out with this (hopefully memorable) meme.

a meme about closure — a large man labeled “inner function” carrying a massive backpack labeled “secret variables from outer function”

I’d love to connect! Find me on LinkedIn, Twitter, and GitHub.

--

--

--

A new tech publication by Start it up (https://medium.com/swlh).

Recommended from Medium

Why React Native?

How to setup npm project for you and your team with automated formatting, linting, testing and more

Developing our first PWA using React

INOI Past Year Problems Practice (Special Sums)

JavaScript Date Object: LOCALE Methods to FORMAT the Date String

Boost JavaScript and React Productivity

The Flatiron Experience Part IV- Capstones-Firebase Auth 2/2

React-ing with the Elements

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Julia Zolotarev

Julia Zolotarev

Software Engineer; hospitality enthusiast; lover of ice cream.

More from Medium

Points to remember about Javascript Defer and Async

The Fat = (Arrow) => {Functions}

Image representation of arrow functions By Yasir Gaji

Creating a Javascript Promise

Mutable & Immutable Array Methods in JavaScript