Cover photo by Andre William on Pexels
Hi, I'm Tauri!
I am a Front End Developer and a student (and enrollment counselor) with Skillcrush, the online coding and design school with a heart! I am open for employment with a company, and working on adding to my skillset every day! This blog is chronicling my most recent projects, so thank you for reading!
This past month, I've been continuing to study You Don't Know JavaScript by Kyle Simpson, using the course by Frontend Masters on the Three Pillars of JavaScript which goes over his first book Up&Going. It's honestly been a DOOZY and I needed to take a foray into studying the this
keyword more before I could even begin to grasp what he was saying on that topic! To explore this
more, I studied the notes by Wes Bos on Prototypes, this, new and Inheritance and by reading over and over again, practicing, and taking notes in a Github Repo, I began to grasp the basics.
Once I got through it, I did the exercise at the end of the course to practice the three pillars, but honestly I need to practice this exercise and others involving this stuff a LOT more. FOREVER. (joking, but not).
In very exciting news, I have started my first Chingu Voyage!! They are an AMAZING organization that gives the opportunity to get real "SCRUM"y team experience, and I would highly recommend them to any budding developers and designers!
I went from being VERY nervous about this voyage to SUPER STOKED! I have an amazing team of all women, all devs (I'm doubling as the Product Owner as well, and me and another dev are doubling ad Designers too bc we're super cool like that š), and we are working on a Recipe App! As someone who loves to cook, this is something I've always wanted to make for myself so I'm so excited to get it started in this setting!
So regarding this past month, checkout my Three Pillars of JavaScript notes, and I'll see you at the beginning of next month with a new team built app in hand!
Into JavaScript
and review class components in the Skillcrush React class under "Updating UIs with Stateful Components"
Intro to the 3 Pillars of JavaScript
- Types/Coercion
- Scopes/Closures
- this/Protypes
Types/Coercion
Types:
- Primitive Types
- Converting Types
- Checking Equality
Primitive Types:
- Objects (non primitive data type)
- Properties can either be accessed with dot notation (i.e.,
obj.a
) or bracket notation (i.e.,obj["a"]
). Dot notation is shorter and generally easier to read - Bracket notation is useful if you have a property name that has special characters in it, likeĀ
obj["hello world!"]
Ā ā such properties are often referred to asĀ keysĀ when accessed via bracket notation. TheĀ[ ]
Ā notation requires either a variable (explained next) or aĀstring
Ā literalĀ (which needs to be wrapped inĀ" .. "
Ā orĀ' .. '
). - Of course, bracket notation is also useful if you want to access a property/key but the name is stored in another variable, such as:
- Properties can either be accessed with dot notation (i.e.,
var obj = {
a: "hello world",
b: 42
};
var b = "a";
obj[b]; // "hello world"
obj["b"]; // 42
- Retrieving values from the properties of objects:
var obj = {
a: "hello world",
b: 42,
c: true
};
obj.a; // "hello world"
obj.b; // 42
obj.c; // true
obj["a"]; // "hello world"
obj["b"]; // 42
obj["c"]; // true
- Methods used on properties of objects and subtypes of objects (arrays and functions):
var a = "hello world";
var b = 3.14159;
a.length; // 11
a.toUpperCase(); // "HELLO WORLD"
b.toFixed(4);
- Symbol is a brand new primitive data type added several years ago
-
v = Symbol()
andtypeof v;
would return "symbol" - "Symbols are often used to add unique property keys to an object that won't collide with keys any other code might add to the object" MDN docs on Symbol
-
- Undefined is an empty type
- A variable that has never been declared (also: undeclared)
- A variable that has been declared but has no value
- Null be behaves strangely depending on the operator applied,
- Example:
var v = null;
typeof v;
returns "object"
- Example:
-
v = function(){};
andtypof v;
returns "function" where function isn't really a primitive data type, but this is useful bc it lets us know we have a VALUE that can be called as a function -
NaN
comes up if you try to apply a mathematical operator to a string, it signifies the invalid use of a mathematical operator more than it indicates that a particular value is "not a number"- ex:
var greeting= "Hello, class!"
var something = greeting / 2;
something; //NaN
Number.isNaN (something); //true
Number.isNaN(greeting); // false
-
new
keyword (very relevant for the discussion on inheritance or closure and to prototypes. This keyword is used with a constructor function to create an object with a proto property that can be used to add functions to the prototype of the object. Code Burst does a great job of breaking this down)- Use for these inbuilt objects:
Object()
- ex:
- Use for these inbuilt objects:
var yesterday = new Date("March 6, 2019");
yesterday.toUTCString(); //"Wed, 06 Mar 2019 06:00:00 GMT"
Array()
Function()
Date()
RegExp()
-
Error()
- Not for these because if we call it with new it'll change the value of the type bc these built in objects are for type coercion:
String()
Number()
Boolean()
- Not for these because if we call it with new it'll change the value of the type bc these built in objects are for type coercion:
- Truthy and Falsy - if we tried to convert a value to a Boolean would it return as true or false?
- Falsy
- "" Empty string
- 0 and -0
- null
- NaN
- false
- undefined
- Truthy
- "foo" (string)
- 23 (number)
- {a:1} (object)
- 1,3
- true
- function(){}
- Everything else NOT falsy
- Falsy
- Coercion Best Practices:
- "If a feature is sometimes useful and sometimes dangerous and if there is a better option then always use the better option" -- "JS The Good Parts", Crockford
- Interpretation comes in when defining what useful, dangerous, or better
- Useful - when the read is focused on what's important
- Dangerous - when the reader can't tell what will happen
- Better - when the reader understands the code
- Equality
- == - allows for coercion
- === - does not allow for coercion, can only be used when types are the same
- In an instance where you are comparing "42" and 42 with
==
, the "42" is coerced into 42. -
<
,>
,<=
, and>=
are used for inequality and follow similar rules to==
because there are no "strict inequality" operators - To decide which one to use, identify what types of data are being used and compared
-Ā If you can be certain about the values, andĀ
==
Ā is safe, use it! If you canāt be certain about the values, useĀ===
. Itās that simple. - == should be about comparisons of KNOWN types (most ideally, don't let your types be unknown) and optionally where conversions are helpful
- (From the Book):
- If either value (aka side) in a comparison could be theĀ
true
Ā orĀfalse
Ā value, avoidĀ==
Ā and useĀ===
. - If either value in a comparison could be one of these specific values (
0
,Ā""
, orĀ[]
Ā ā empty array), avoidĀ==
Ā and useĀ===
. - InĀ allĀ other cases, youāre safe to useĀ
==
. Not only is it safe, but in many cases it simplifies your code in a way that improves readability. ### Scope/Closure
- If either value (aka side) in a comparison could be theĀ
- if a variable is undeclared, then just referenced within a function, JS will automatically declare that variable in the global scope. As in this example:
var teacher = "Kyle";
function otherClass() {
teacher = "Suzy";
topic = "React";
console.log("Welcome!");
}
otherClass(); // Welcome!
teacher; //Suzy
topic //React
- Undefined vs undeclared (emptiness)
- undefined has been declared but doesn't have a value
- Undeclared has never been declared
- This function is assigned to a variable, but has not been given its own name so it is an "anonymous" function expression
var clickHandler = function() {
...
};
- This function is assigned to a variable AND is a named function expression
var keyHandler = function keyHandler () {
...
};
-
Naming your function clearly allows you to understand exactly what a function is doing if it's named descriptively.
- In this function, you can infer that the id property is being extracted from the person object
var ids = people.map(person => person.id);
- But the name of this function when applied makes it explicitly clear
var ids = people.map(function getId(person) { return person.id; });
- Another example from a "promise chain":
getPerson() - then(person => getData(person.id)) - then(renderData);
- Is not as descriptive as:
getPerson() - then (function getDataFrom(person) { return (getData(person.id); }) - then(renderData);
-
IIFE ("iffys") = immediately invoked function expressions
- They have a (); to immediately invoke the expression
- This allows us to encapsulate the scope by wrapping a function around it so it doesn't affect outside scoped code
- the set of parentheses wrapping around the function allow it to be a function expression and not a declaration. The parentheses at the end is the part that immediately invokes/executes the function
- An example:
var teacher = "Kyle"; ( function anotherTeacher() { var teacher = "Suzy"; console.log(teacher); //Suzy } ) (); console.log(teacher); //Kyle
Block scoping achieves the same thing. Let and a curly brace block will keep the block scoped
var teacher = "Kyle";
{
let teacher = "Suzy";
console.log(teacer); // Suzy
}
console.log(teacher); // Kyle
- Closure
- when a function "remembers" the variables outside of it, even if you pass that function elsewhere
- Example from the book:
function makeAdder(x) {
// parameter 'x' is an inner variable
//inner function 'add()' uses 'x', so it has "closure" over it
function add(y) {
return y + x;
};
return add;
}
- The reference to the innerĀ
add(..)
Ā function that gets returned with each call to the outerĀmakeAdder(..)
Ā is able to remember whateverĀx
Ā value was passed in toĀmakeAdder(..)
. Now, letās useĀmakeAdder(..)
var plusOne = makeAdder( 1 );
var plusTen = makeAdder ( 10 );
plusOne ( 3 ); // 4 <-- 1 + 3
plusOne ( 41 ); // 42 <-- 1 + 41
plusTen ( 13 ); // 23 <-- 10 + 13
- When we callĀ
makeAdder(1)
, we get back a reference to its innerĀadd(..)
Ā that remembersĀx
Ā asĀ1
. We call this function referenceĀplusOne(..)
. - When we callĀ
makeAdder(10)
, we get back another reference to its innerĀadd(..)
Ā that remembersĀx
Ā asĀ10
. We call this function referenceĀplusTen(..)
. - When we callĀ
plusOne(3)
, it addsĀ3
Ā (its innerĀy
) to theĀ1
Ā (remembered byĀx
), and we getĀ4
Ā as the result. - When we callĀ
plusTen(13)
, it addsĀ13
Ā (its innerĀy
) to theĀ10
Ā (remembered byĀx
), and we getĀ23
Ā as the result. - we can observe closure when a function is treated as a value, like when it's called in a callback function, or returned elsewhere, or returned and treated as a prop where we pass the object around
function ask(question) {
reutn function holdYourQuestion(){
console.log(question);
};
}
var myQuestion = ask("What is closure?");
myQuestion(); //What is closure?
###this / Prototypes
- a function's
this
, which is an "identifier" references the execution context for that call, determined entirely by how the function was called.- Reference the code in the js-playground repo under new-this for a code example of this
- a
this
-aware function can thus have a different context each time it's called, which makes it more flexible and reusable. Kyle refers to it as "dynamic context"- Implicit binding
- In this example,
workshop.ask
is implicitly binding "workshop" as thethis
keyword
- In this example,
- Implicit binding
var workshop = {
teacher: "Kyle",
ask(question) {
console.log(this.teacher, question);
},
};
workshop.ask("What is implicit binding?");
// Kyle What is implicit binding?
- Explicit binding
- In this example, myContext is bound to be the
this
keyword. The ask function is called with.call
and handed myContext to be thethis
keyword
function ask(question) {
console.log(this.teacher, question);
}
function otherClass() {
var myContext = {
teacher: "Suzy"
};
ask.call(myContext, "Why?"); //Suzy Why?
}
otherClass();
- prototypes are what the
class {}
keyword is built on top of - the
class {}
keyword simplifies the prototype system, but using prototypes allows us to see what's going on under the covers forclass {}
- In this example, there is no
ask
method ondeepJS
orreactJS
but it refers to the ask method on the prototype anddeepJS
andreactJS
are handing the object that thethis
keyword will point to in the new instances of Workshop
function Workshop(teacher) {
this.teacher = teacher;
}
Workshop.prototype.ask = function(question) {
console.log(this.teacher, question);
};
var deepJS = new Workshop ("Kyle");
var reactJS = new Workshop("Suzy");
deepJS.ask("Is 'prototype' a class?")
//Kyle Is 'prototype' a class?
reactJS.ask("Isn't 'prototype' ugly?");
//Suzy Isn't 'prototype' ugly?
- When using the
class {}
keyword instead, we can do the same thing of creating and referencing to prototypes but while using cleaner syntax:
class Workshop {
constructor(teacher) {
this.teacher = teacher;
}
ask(question) {
console.log(this.teacher, question);
}
}
var deepJS = new Workshop("Kyle");
var reactJS = new Workshop("Suzy");
deepJS.ask("Is 'class' a class?");
// Kyle Is 'class' a class?
reactJS.ask("Is this class OK?");
// Suzy Is this class OK?
Top comments (0)