Select Page

I am taking Udacity’s Intermediate JavaScript Nanodegree. The following are my thoughts on the Object Oriented section (part 1 of the course).

As I imagine the content of this course will change (if anyone at Udacity pays attention to what I am going to say about this course, I think they will have to change it), note that the version I am reviewing is current as of September 5, 2022.

Objects in Depth

The first part of the Objects section is a pretty straight-forward review of objects, which Udacity describes as key-value pairs. The review includes accessing properties via dot notation and bracket notation, creating objects with constructor functions and with literal notation (they say the recommended method is literal notation, because it is less “verbose”), modifying adding and deleting properties, and methods (which they define as object properties that are functions), using the “this” keyword inside methods to refer to the object it is called on. So far so good.

But I struggle with “this” later on, so let’s look at their first example before moving on.

const triangle = {
          type: ‘scalene’,
          identify: function () {
          console.log(`This is a ${this.type} triangle.`);
    }
};

triangle.identify(); 
The output is ‘This is a scalene triangle.’

Because the identity() method is called on the triangle object, “this” in identity() is set to the triangle object; so “this.type” points to triangle’s “type” property, which is ‘scalene’.

Seems reasonable enough.

The section “Beware of Globals” is OK, except I am left confused about let and const. If we declare a variable with var in the global scope (ie: not inside any function, but in the scope of the entire program), we create a global variable, which is bad because it can lead to many problems including “tight coupling” and “name collisions” (neither of which I understood very well, but I am happy to take this programming anti-globalism on faith for now). They explain that global properties are properties on the “window” object (an object provided by the browser — not JS — that has access to information about the screen, like “window.scroll” = the vertical position of the page). But then they say that only the “var” keyword sets properties to window — that declaring variables with the “let” and “const” keyword does not. But I have been told in previous courses to never use “var”, but only “let” and “const”. So does that mean I don’t need to worry about global variables, since I’m not using “var” anyway? I am left wondering.

It does seem clear that declaring a functions outside of an object or other object, and without assigning that function to a variable with either “let” or “const” should be avoided. Because global functions are methods on the “window” object, and that (creating properties or methods on the “window” object) we definitely want to avoid — because that, I think, is what the section “Beware of Globals” is warning us against. But still: What happens when I declare a variable with “let” or “const” at the global scope? They don’t get set to the “window” property; but what property do they get set to?; and aren’t they still global variables (since they are still declared outside of the scope of anything except the entire program)? This I’ve not yet figured out.

With the “Extracting properties and methods” section I went back to feeling like I knew what was going on. Object.keys(SOMEOBJECT); returns an array of the keys of SOMEOBJECT, while Object.values(SOMEOBJECT); returns an array of the values of SOMEOBJECT. OK, that’s fine. I get that.

Functions at Runtime

This is the second part in the object-oriented programming section of Udacity’s Intermediate JavaScript Nanodegree.

I found it confusing. They start out saying that functions are objects — or maybe they are; and they are going to tell me in this lesson. But I took the lesson and I’m still not sure in what sense it is true to say that a function is an object. Also, they call this segment, “Functions at Runtime”, but they never clarify what they mean by that, and I am not sure what they mean.

“Runtime” is when a program is being executed. Is this lesson about all functions, since all functions happen when the program is executed? Or only about those functions that run themselves (without being called from somewhere else).

This is a problem with this nanodegree in general: It lacks simple, straightforward introductions and clarifications of terms. If you name a chapter “Functions at Runtime”, you should explain in the beginning, middle, and end what that means, and how different types of functions fit into (or don’t at all fit into) that umbrella. But they never take the time to say what they mean with “Functions at Runtime”. I will now go over this section again and see if I can figure out what they mean. 

First Class Functions

The “First Class Functions” segment is easy enough: In JS, functions are first-class, which means you can treat them like other elements (“such as numbers, strings, objects, arrays, etc.”). This means you can store functions in a variable, return them from another function, or pass them as arguments to another function. They go on to say that “Note that while we can, say, treat a function as an object, a key difference between a function and an object is that functions can be called (i.e., invoked with ()), while regular objects cannot.” So, I guess they are saying JS functions are objects; but I don’t think they ever explain that in more depth than in this little aside that I just quoted. And I don’t see how functions are objects just because they are fundamental elements. In what sense is an object a key/value pair? That had been their original definition of objects — key/value pairs.

Besides the confusing semi-revelation that JS functions are objects that can be invoked, the “First Class Functions” segment was pretty straightforward. It consisted of an example each of functions being stored in variables, returned from other functions, and passed as arguments to other functions.

Callback Functions

“Callback Functions” is the next (second) segment in the “Functions at Runtime” part of the “Object-Oriented Programming” section. 

These definitions were easy to digest: 

“A function that takes other functions as arguments (and/or returns a function, as we learned in the previous section) is known as a higher-order function. A function that is passed as an argument into another function is called a callback function.”

Then they say that callback functions “allow you to build your applications with composition, leading to cleaner and more efficient code.” Let us see if they ever explain what they mean by that, or even use the word “composition” again in this section. I bet they don’t. But let’s check. No, they don’t. They italicize like it’s a big deal, but they do not define or even mention “composition” in the rest of this segment. I’ll keep an eye out for it in the subsequent lessons.

This segment is mostly devoted to built-in array methods. They go over forEach(), map(), and filter(). Let’s come back to those after we look at the example from the exercise:

function each(array, callback) {
             for (let i = 0; i < array.length; i++) {
                   if (callback(array[i]) {
                   console.log(array[i]);
               } 
       }
}

function isPositive(n) {
                return n > 0;
  };

each([-1, 0, 3], isPositive); returns 3

Note that “each” is a higher order function because it accepts another function as an argument, and that “isPositive(n)” is a callback function because it is passed as an argument into another function. Notice that inside of “each”, “isPositive” is made to go over each element in the array. “isPositive” will of course check to see if a given element is positive or not, and then output only the positive elements.

It’s a little confusing to think of the built-in array methods forEach(), map(), and filter() as higher order functions, since the callback functions are usually written write inside of these array methods. Take their forEach() example:

[1, 2, 3, 4, 5, 6] .forEach(function logIfOdd(n) {
                          if (n % 2 !== 0 ) {
                          console.log(n);
         }
});

It still feels weird to me to call the logIfOdd() function a callback function when it is included right there in the higher order function. But I guess it’s still a callback function, and we just have to accept that. logIfOdd(n) could’ve been declared outside of the forEach function with a variable, and then passed in to the forEach() function.

Anyway, these array methods are useful.

forEach() applies a callback function to each element in an array; map() does the same, but forEach() doesn’t return anything (it just lets the callback function do its work [I guess; I am a little confused here; they say forEach() doesn’t return anything, but functions always do; I am going to have to look into this more], and map() returns an array of the elements after the callback function has worked on them.

filter() also goes over each element in the array, applies a callback function on each one, and returns an array; but the filter() array consists only of the elements that meet the criteria posed by the callback function.

Callback functions I find a little difficult to follow because of how they twist into the higher order function. But I guess this just takes practice to get used to

Scope

This segment is OK. At the outset, they say they are not covering lexical scope (block vs function scope) here, but only runtime scope, which is created when the function is run.

“This scope represents the context of the function, or more specifically, the set of variables available for the function to use.”

Code inside a function can use (1) arguments of the function, (2) variables declared inside the function, (3) variables in the scope of the parent function, (4) variables with global scope.

The var keyword is either function or global scoped: if it is declared inside a function, anything in that function can use it; if it is declared outside of all functions, anything in the program can use it.

The let and const keywords are either block or global scoped. As per Udacity’s free ES6 course, var variables are “hoisted” to the top of whatever function they are declared within. But the scope of let and const does not leave the code block (denoted with {} in JS) they are declared in. Per Udacity (and pretty much everyone else), var is messier and more dangerous, and we should just use let and const now. Neither let nor const can be redeclared; the distance between them is that let can be reassigned, and const cannot. So if you are going to give variables more than one value, use let; if not, use const.

They quickly cover the scope chain: JS starts looking for a variable in the code block (assuming you are using let or const) that asked for the variable, and then moves outward, looking for the variable in the parent element (if one exists) and then in the global scope.

If you reassign a variable / use the same variable name twice in the same scope chain: the last reassignment (before the final execution of the function) is the one that ends up being used by the function. 

I do have one critique of this section: It seems like it was written for var and not completely updated for let and const. Specifically, they mention more than once that JS is a function-scoped language, but that seems kind of misleading and confusing now that everyone says we should forget var and stick to let and const, which are block scoped.

Closures

OK, second to last segment in the “Functions at Runtime” section. 

The current (9/6/22) MDN definition of closure is more useful than the one Udacity quotes in this lesson. Here’s the current definition.

“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.”
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

Udacity says that 

“Every time a function is defined, closure is created for that function. Strictly speaking, then, every function has closure! This is because functions close over at least one other context along the scope chain: the global scope. However, the capabilities of closures really shine when working with a nested function (i.e., a function defined within another function).”

This is more confusing than the above MDN quote. I am not sure about the truth of what Udacity is saying about every function closing over the global scope. However, everyone seems to agree that closure is helpful in this way: by nesting functions, we can make the variables declared in the parent function private but still accessible. And this encapsulation helps to minimize errors.

Here’s a good example of closure from one of Udacity’s closure exercises:

function outerFunction () {
let num1 = 5;
return function(num2) {
console.log(num1 + num2)
}
}

let result = outerFunction();

result(10);

The output is 15. 

I’m a little confused about how you can pass an argument into result and have that argument make its way all the way down to the inner function. But I’m not sure that’s a confusion about scope, but rather about how nested functions pass arguments. Anyway, the num1 variable is kept private, but is still used inside the function when it is called. I think this combination of private and public is the main virtue of closures. Because object oriented programming seeks to keep variables as local as possible — in order to minimize confusions.

Udacity says closure is particularly useful for “passing arguments implicitly” and “at function declaration, storing a snapshot of scope.” I think they should’ve explained both of these concepts explicitly. I think this is another example of terminology that they act like they discussed, and maybe they did, but not using that terminology. I guess I will have to go back and try to see what they mean, but it would be better if in the examples themselves, they say something like, “here we are passing an argument implicitly. That is useful because … You would use this when trying to solve these kinds of problems … “. In general, this is the kind of super easy gentle-underhand pitches that I think Udacity should be lobbing at us. We can be challenged trying to apply the information. We don’t need to be challenged trying to learn it. 

Immediately Invoked Function Expressions (IIFE)

Almost through the Functions at Runtime section! This is the last part of that section.

Function declaration vs function expression:

declaration:
function sayYes() {
                  console.log(“Yes.”);
}

expression:
const myFunction = function sayYes() {
                console.log(“Yes.”);
}

Immediately invoked functions are called right after they are declared.

They make them by putting the parentheses around the function and then adding parenthesis at the end:

(function () {etc}) (); OR (function () {etc} ());

You can also put parameters in that final () if you want.

I am not sure what the point of them is. They are used to not pollute the global scope and to keep variables private with closure. But don’t we keep variables private now just by using const and let inside of functions?

I’m going to come back to this section later.

I want to figure out the Classes and Objects section first.

Classes & Objects 

This is the section that blew my mind. They never defined a “class”! Or even really talked about them. That, at any rate, is my memory. Let’s check again.

Well, I’m not quite right.

Early in the introduction they say “classes (or categories)” and then in the introduction’s summary they say:

In the next section, we’ll take a dive into object-oriented JavaScript, beginning with constructor functions. If you’ve had experience with object-oriented programming in other languages (e.g., Ruby, Python, etc.), you may be surprised to learn that JavaScript does not have a traditional class system (namely, one where the compiler does a lot of organizing out of sight). Instead, the class system is built directly using functions and objects. So rather than using a special class syntax, in JavaScript we define constructor functions. Let’s dive right in!

Constructor Functions

In this first segment, they show how to make constructor functions and then instantiate objects based on them.

function SoftwareDeveloper() {
  this.favoriteLanguage = 'JavaScript';
}

let developer = new SoftwareDeveloper();

You have to have the .this in the constructor function and the new before the new objects.

The .this Keyword

Per Udacity: “when invoking a constructor function with the new operator, this gets set to the newly-created object”

They go on:

“The value of this is actually not assigned to anything until an object calls the method where this is used. In other words, the value assigned to this is based on the object that invokes the method where this is defined.”

There are four ways to call functions, and each way sets this differently.

First, calling a constructor function with the new keyword sets this to a newly-created object. Recall that creating an instance of Cat earlier had set this to the new bailey object.

Calling a function that belongs to an object (i.e., a method) sets this to the object itself. Recall that earlier, the dog object’s barkTwice() method was able to access properties of dogitself.

Calling a function on its own (i.e., simply invoking a regular function) will set this to window, which is the global object if the host environment is the browser

Setting our own .this

Copyright: AMW