Austen's LJSTHW Journal


#1

Hello! I’m studying from the draft version of LJSTHW. I’ll be taking notes in this thread. I am also keeping a LJSTHW gitlab repo. When my curiosity veers off from material directly related to LJSTHW exercises, I might write about it on my blog.

Computer system:

  • Acer Chromebook CB3-431
  • Chrome OS 70, beta channel
  • Linux Apps for Chromebook enabled
  • Node.js v10.12.0

The book and videos have been straightforward. I followed the Linux version of the exercise 0 video to install Node.js on Chrome OS. My editor is simply Vim. VSCode is unnecessary at this stage so I did not bother installing it.

Exercises 01-04 are completed. They all run without problems.


#2

Today I worked on Exercises 05-11. From what I had already learned about JavaScript, I thought I wasn’t really going to like the language very much. However, as I’m going through Zed’s book and reading online docs, my enthusiasm is definitely growing, especially for Node.js.

Ex10 is probably my favourite so far. I tried to figure out how to write to a file. For whatever reason, I was able to overwrite an existing file, but I wasn’t able to create a new file. I wiped most of my first attempt and started over with file IO. Eventually, I got readFileSync and writeFileSync working well enough to move on, but I’d really like to learn how to use file descriptors and callbacks. It all looks complicated up front, but I remember feeling the same way about Python.

Anyhow, this article helped me a bit with understanding files in node.js.

Here’s my ex10 attempt.

Looking at the repo now, I can see a couple of .swp files. I have a feeling those are from my Vim sessions. I’ll have to see about editing the vim or repo configs so temporary files don’t get added to the commit.


#3

This little tidbit was very helpful for solving the ex12 Extra Challenge.

This is how you scoop up a variable number of arguments like with *args in python. I don’t think it handles keyword args, but that’s ok for now because I’m pretty sure console.log doesn’t have named parameters.


#4

@austen, You could also use the arguments object:


#5

Hey thanks. I was looking at the arguments object, but I found it a little confusing when I tried to use it.

// using rest parameters works
const wrapMax = (...args) => {
    console.log("\nwrapMax: ", Math.max(...args));
}

wrapMax(12, 24, 32, 33, 383, 5); 

// Trying to use the argument object here...
const wrapUseArgObj = () => {
        console.log("\nwrapNoRest: ", 
        // Math.max.somthinsomthin...// what do I write here?
        );  
}

wrapUseArgObj(525, 5238, 532, 532 ,2, 3532, 3); 
~                                              

Does the argument object still work with these functions? According to this article, I don’t think it will, but I could be misunderstanding what an arrow function is.


#6

You are correct. The arguments object doesn’t work with arrow functions.

So I’d keep using the rest parameters. But just be aware of the arguments object in case you run into it in the wild.


#7

Today I worked on Exercise 12-19. No surprises yet. Anonymous functions and callbacks are a little weird for me. They seem to be similar to lambda functions in Python, but I only used those processing/sorting lists of objects according to a particular property. Anonymous functions and callbacks seem to be all over the place in JavaScript. I guess that means I’ll have to figure them out soon.

The great thing about learning a new language is that, although it seems mostly the same in terms of basic logic, it really is amazing how much the syntax affects how accessible certain features can be. I learned that before the rest argument of ES6, you had to use a variety of ugly-looking techniques to pass args from wrappers to function calls, whereas Python makes it so easy, I just assumed it was a feature common to most languages.


#8

Today I went back to Exercises 18 and 19 to type out my solutions instead of just doing them on paper/in my head. I’m glad I did!

I also spent some time trying to fix the syntax highlighting in vim and the colour scheme in my gnome-terminal. I think it looks pretty good now. With all the pink and green, it’s kind of a floral theme.


#9

Today, I started and completed ex20. I filled in the remaining rooms. No big problems. Zed’s example rooms made it much easier to do.


#10

I’m playing with ex21, the first OOP lesson.

I wanted to see if I could create objects with the properties “out of order”.
IE

  1. call the object constructor
  2. set an anonymous function as a property (essentially a method) which references another property, “name”
  3. declare and assign property, “name”

I wondered if I could break the instantiation by referencing “name” in the anonymous function before “name” is declared. It turns out it doesn’t cause any problems. I guess the references only kick in once the method/anon-function is called.

Here’s my experiment using Zed’s code in both JavaScript and Python

#!/usr/bin/env node
// riffing on Zed's example


// we need a way to build these automatically
const Person = (name, age, eyes) => {
    // This makes an obj for the data
    let obj = { 
        //name: name,
        age: age,
        eyes: eyes,
        talk: (words) => {
            // coolest part is obj here will keep a reference
            // Aus:will this break because the obj isn't instantiated yet?
            console.log(`I am ${obj.name} and ${words}.`);
        },
        name: name,
    }   

    // and return our new person
    return obj;
}

let chuck = Person('Chuck', 24, 'purple');
chuck.talk("how about a hug for Chuck?");

Here’s the same idea written in python.

#!/usr/bin/env python3
# riffing on Zed's example... IN PYTHON!


# we need a way to build these automatically
class Object(object):
    pass
    
def Person(name, age, eyes):
    # Aus: unfortunately, I had to create the Object class because the built-in
    # object class doesn't have a __dict__ attribute.
    person = Object()
    person.__dict__ = { 
                    'age': age,
                    'eyes': eyes,
    # A:will this break because person isn't instantiated yet?
                    'talk': lambda w: print("My name is", person.name, "and", w)
    }   
    person.name = name
    return person

chuck = Person('Chuck', 24, 'purple')
diane = Person('Diane', 33, 'grey')
chuck.talk("how about a hug for Chuck?")
diane.talk("forget about it.")

I have a feeling that I don’t even need to declare the “name” property in the constructor function. I can probably tack it on after a Person is instantiated so long as I do so before the “talk” method is called. Just guessing tho… Aw, why don’t I just try it out in Python to see if it works? …

#!/usr/bin/env python3
# riffing on Zed's example... IN PYTHON!


# we need a way to build these automatically
class Object(object):
    pass

def Person(name, age, eyes):
    # A: unfortunately, I had to create the Object class because the built-in
    # object class doesn't have a __dict__ attribute.
    person = Object()
    person.__dict__ = {
                    'age': age,
                    'eyes': eyes,
    # A:will this break because person isn't instantiated yet?
                    'talk': lambda w: print("My name is", person.name, "and", w),
                    'flirt': lambda : print(person.name,":", person.charm)
    }
    person.name = name
    return person

chuck = Person('Chuck', 24, 'purple')
diane = Person('Diane', 33, 'grey')
chuck.talk("how about a hug for Chuck?")
diane.talk("forget about it.")
chuck.charm = "<cheesey smile>"
chuck.flirt()
diane.charm = "<rolls eyes>"
diane.flirt()

And here’s the output.

My name is Chuck and how about a hug for Chuck?
My name is Diane and forget about it.
Chuck : <cheesey smile>
Diane : <rolls eyes>

So my guess was correct. Moving on to ex22!


#11

This experiment brought up an interesting point about Python 3.5: lambda functions cannot handle expressions containing f-strings. I can’t think of a good reason as to why that isn’t possible. I wonder if it’s a bug that has been fixed in Python 3.7.


#12

I’m reading about prototypes in JavaScript. It’s quite a mindful! I can handle the basic idea of shadowing because it’s a lot like how lexical scope works, but I’m wondering why we need __proto__ instead of just accessing [[prototype]] directly. Also, why in the world does the constructor function need a .prototype property attached to it? Is it passed onto the constructed object implicitly, or do we have to manually set obj.__proto__ = constr.prototype? That’s why I’m reading!


This next article explains .prototype vs __proto__ vs [[prototype]]. Yikes!

That last article led me down the following rabbit hole.

I have a lot to learn.


#13

This is an update to a script I posted in another thread where I used a Player prototype for a hypothetical game. I posted some code where a subclass of Player, teamPlayer, has all instances sharing the same score. Any changes to the score in a teamPlayer cause a change in the score for all teamPlayers because their score property has a “set” method defined to point to the score property of the teamPlayer.__proto__ (prototype). Similarly, there is a “get” method for reading the value of score.

In this updated version, I’ve added another Player subclass, soloPlayer. A soloPlayer instance is meant to keep its own individual score. It does not refer to its __proto__.score. Here’s the demo!

#!/usr/bin/env node
// This is an experiment to show how set/get methods can be used to make a
// generic interface to common-yet-different properties of subclasses.
// In this case, teamPlayers share a common score, whereas soloPlayers
// have an individual score
class Player {
    constructor (value) {
        this.score = value
    }

    doubleScore () {
        this.score *= 2;
    }
}

class teamPlayer extends Player {
    // using set/get methods to make score property refer back to prototype
    // so that all players share the same score
    set score(value) {
        this.__proto__.score = value;
    }
    get score() {
        return this.__proto__.score;
    }
}

class soloPlayer extends Player {
}

// even when each teamPlayer is instantiated with a unique argument, the value
// is assigned to the __proto__ score
let Baba = new teamPlayer(0);
let Jojo = new teamPlayer(10);
let Solo = new soloPlayer(13);

console.log("Baba score: ", Baba.score); // 10
console.log("Jojo score: ", Jojo.score); // 10
console.log("Solo score: ", Solo.score); // 13

// it also applies to assignment after instantiation
Baba.score = 5;
Jojo.score += 2;
Solo.score += 10;

// We can clearly see here that the soloPlayer doesn't read its score from
// soloPlayer.__prototype__.score. Instead, the Player.constructor's "this"
// refers directly to the instance of Solo, the soloPlayer.
console.log("Baba score: ", Baba.score); // 7
console.log("Jojo score: ", Jojo.score); // 7
console.log("Solo score: ", Solo.score); // 23

Baba.doubleScore();
Jojo.doubleScore();
Solo.doubleScore();

// See how doubleScore doesn't need to be rewritten for each subclass?
// The set/get methods hide the innerworkings of the teamPlayer
// score property from the doubleScore implementation.
console.log("Baba.doubleScore(): ", Baba.score); // 28
console.log("Jojo.doubleScore(): ", Jojo.score); // 28
console.log("Solo.doubleScore(): ", Solo.score); // 46

Now I have a new question: When I read this script in my Caret editor, it issues a warning that the __proto__ property is deprecated. If that’s so, what should I use in its place?


#14

Today I refactored the OOP game in ex24. I eliminated the Game class altogether and switched to a game-loop rather than stacking Room calls. I moved the hitpoints and all the game methods to the Room class. The hitpoint property is accessed using set-get methods which refer to the room’s __proto__ property.
This property is deprecated, but it worked for my script. I’ll leave it at that for now, but I do want to go deeper into prototypes.
It’s very confusing. I thought I knew what a classes, objects and instances were. I had assumed the prototype had something to do with the superclass, but now I don’t think it does.




I still have lots of reading to do, but based on what I’ve read (since starting on prototypes) is that I misunderstood. I thought the prototype was a reference to the superclass, but now I think it’s like a primary (prototypical?) instance of an object. The class and its constructor are NOT the prototype.
I think I will read a little more before I move on to ex25 (functional programming).


#15

From the Wikipedia entry on prototype-based programming

A common criticism made against prototype-based languages is that the community of software developers is unfamiliar with them, despite the popularity and market permeation of JavaScript. This knowledge level of prototype-based systems seems to be increasing with the proliferation of JavaScript frameworks and the complex use of JavaScript as the Web matures.[ citation needed ] ECMAScript 6 introduced classes as syntactic sugar over JavaScript’s existing prototype-based inheritance, providing an alternative way to create objects and deal with inheritance.[7]

I think Zed had said something about this (or maybe I read about it in another article I shared): Classes in JS are just syntactic sugar to cover up the complexity of the existing prototype implementation.

@zedshaw: When should I approach JS as class-based vs prototype-based? I’m interested in prototypes, but it does seem a lot more complicated than classes (e.g. cloning and prototyping vs instantiation and inheritance).


#16

Today I worked on ex26 to ex29. This is the section on functional programming. I found ex26 and ex27 familiar. I remember chaining function calls from Python. Filter, map and reduce are also familiar.

The struggles started in ex28. It still has me scratching my head, but it could also be because a lot of the example code is missing.

The puzzle seems ok, but I’m not sure as to why/how I could get rid of the return statement as suggested in the closure comment. The pending video or some more supporting text would greatly help me “get” ex28.

Although I’ve read and worked through ex29, I don’t understand that one either. I’m going to have to study the example code tomorrow.


#17

Today was a deep-dive into ex24 to better understand prototypes. I know the exercise has changed to class inheritance, but I really want to understand as much as I can about prototypal inheritance. Here are two resources I found extremely helpful. Of course the MDN reference is invaluable for getting to know the Object methods but I’d really like to emphasize how much this particular video cleared up constructors for me.


I’ve already started on a write-up of the key ideas that are helping me understand prototypal inheritance. I hope that by laying those ideas out in a systematic fashion, I can get feedback and revise my understanding even further.

The first write-up should be posted tomorrow or Saturday.


#18

Welllllllllllllllllllllllll, that is the million dollar question. I went with the new style of classes because it seems they’re going to add additional type safety features and try to do away with the prototype based stuff, but who knows. I’d say, just stick with classes as they’re easier to write and then if you need to do some magic hacking dip into prototypes.


#19

Today I wrote some of my distilled notes. I’m finding prototypal inheritance much more difficult to summarize than classical inheritance mostly because I can’t use terms like “superclass” and “subclass”… What are the parallels to those terms when talking about prototypal inheritance? Vocabulary seems to be the key here.


#20

I’m still working on the notes and doing more reading to make sure they’re as accurate as possible.