Wrote this document for my own learning purposes to extend my javascript/programming skills. Made it public for other people who think this is useful for themselves. I'm doing my best to write my explanations down in my best english, as straight, practical and as simple as possible. I'm not going in on deep details. Providing code aswell. At this stage of writing, I probably skip and jump over (important) things, but that would probably be because I don't know about it yet. Improvements will come in time :-)
I personally will use this as my reference or handbook so that I have the 'knowledge' in one place until I have it in my head.
Basic terms/jargon and inner workings of JavaScript explained to understand the languague better.
WIP
The rules to write valid code is called the syntax
. In normal languague this can be compared with the spelling of words and writing valid sentences (according to universal rules).
Referred as a group of words, numbers, operators that perform specific tasks. I personally see this as a 'sentence' of text compared to human language.
const firstZelda = 1986;
We assign the value 1986
to the firstZelda
variable. This is a simple statement.
Expressions are almost equivalent of statements. However, statements are built with expressions. I'd like to think expressions as 'words' building up a sentence, or in JS, expressions building up a statement.
Operators are the pieces of syntax we use to perform actions on variables or values.
const princessPeachKidnapped = 12; // = is an operator to assign values to variables.
const kidnappedByBowser = princessPeachKidnapped - 4; // - minus sign is an operator.
Values that are directly written in the code, such as a String
: 'Surf Harp!'
or a Number
: 26
or Booleans
: true; false;
.
Formal function declarations:
function getTotalOfLifts(weight) {
return weight;
}
Function expression:
var deadlift = function(weight) {
return weight;
}
Formal variable declarations
javascript var squat = 205;
JavaScript has 5 datatypes that are passed by value: Boolean, String, Number, undefined and null
. Those are called primitive values. JavaScript also has datatypes that are passed by reference: Array, Function and Object
.
What is the difference? When changing a single non-primitive variable, we assign the value to the variable. The following code illustrates the difference:
let itemSlotA = 'Sword';
let itemSlotB = 'Hookshot';
let temp = itemSlotA; //temp contains the value 'Sword'
itemSlotA = itemSlotB; //itemSlotA contains the value 'Hookshot'
itemSlotB = temp; //itemSlotB contains the value 'Sword'. ItemSlotA still contains 'Hookshot'.
temp = null; // Temp is 'null', while itemSlotB is still 'Sword' and not 'null'.
However, when using primitive values, we assign a reference to the variable.
let dungeons = ['Key Cavern', 'Eagle Tower', 'Catfish Maw'];
let moreDungeons = [];
moreDungeons = dungeons; // moreDungeons now contains a reference from dungeons.
moreDungeons.push('Face Shrine');
dungeons // ['Key Cavern', 'Eagle Tower', 'Catfish Maw', 'Face Shrine'];
moreDungeons // ['Key Cavern', 'Eagle Tower', 'Catfish Maw', 'Face Shrine'];
The dungeons array and moreDungeons array now contain the same reference. Changing the array changes the copied array aswell because it's a reference.
"Boxing" is wrapping an object around a primitive value. For instance, "I'm not screaming".toUpperCase()
returns (as you might have guessed) an uppercase string
.
In the previous example we see a string
called a method on, while it actually can'ty have methods. However when the engine sees accessors of properties coming from a primitive root (in this case string
), it converts the primitive value to a equivalent object
which actually can access those methods like .toUpperCase
.
JavaScript knows two types of scope (without ES6 scoping taken into account):
- Global Scope
- Local Scope
Consider this piece of code:
// global scope
var foodToCook = ['Hyrule Bass', 'Hot-Footed Frog', 'Baked Palm Fruit'];
// function scope
function cook() {
console.log(foodToCook) // undefined
var foodToCook = ['Fortified Pumpkin', 'Goat Butter', 'Fresh Milk', 'Tabantha Wheat']; // variable bound to the function scope
console.log(foodToCook) // ['Fortified Pumpkin', 'Goat Butter', 'Fresh Milk', 'Tabantha Wheat']
}
Accessing the foodToCook
variable in the function scope returns undefined
because it is not declared in the functions scope whenever the code is trying to access it. Hoewever, one line later, the variable is declared but important to note is, that it is hoisted
to the top and therefore returns undefined
. Would you not define a variable in the function scope in this case, JavaScript tries to look into the higher scopes if it finds an identifier which is the variable.
A difference is when let
and const
are used in this case instead of var
:
let foodToCook = ['Hyrule Bass', 'Hot-Footed Frog', 'Baked Palm Fruit'];
function cook() {
console.log(foodToCook) // ReferenceError
let foodToCook = ['Fortified Pumpkin', 'Goat Butter', 'Fresh Milk', 'Tabantha Wheat'];
console.log(foodToCook)
}
cook();
JavaScript can be weird and do things unexpectedly, which may cause bugs. Here is a list of things that I think developers should know while writing JavaScript:
JavaScript handles type values very loosely, unlike other languages. Variables do not need a type value, and can hold any type of value without warnings or errors in the program which you can change at will:
let whichTypeOfValue = 100;
whichTypeOfValue = 'I\'\m a string right now!';
whichTypeOfValue = false; // Not anymore!
This may look interesting to use (because it is), but you should be careful and know what value types you expect in your variables. Consider a scenario where you rely on a type of value and testing it, but the value changes type.
- You may be expecting that a value produced by an expression
null
returns a type ofnull
aswell, but it doesn't:
javascript typeof null //returns 'object'
- Hoisting is a behaviour in JavaScript where the declaration of the variable, is moved to the top of the scope, no matter where it is declared. Consider this:
var teams = ['Little Gigant', 'Orpheus', 'The Kingdom'];
function getTeamNames() {
teams = ['Inazuma Japan', 'Unicorn', 'Knights of Queen'];
console.log(teams) // output: Inazuma Japan', 'Unicorn', 'Knights of Queen'
var teams;
console.log(teams) // output: Inazuma Japan', 'Unicorn', 'Knights of Queen'
}
getTeamNames();
console.log(teams) // output: 'Little Gigant', 'Orpheus', 'The Kingdom'
Important to note is that hoisting happens per scope.
- 'Declaring' your variables without
var
will make your variable global to the outer scope, despite in what scope 'declared' (yes, declared between quotes, since this way you can declare variables but it is not wished according to the rules)
//global scope
game = 'Link\'\s Awakening';
(function() {
game = 'Super Smash Bros.'; // Warning! Auto-global rule applies here and sets the 'game' variable value to the new value!
})();
Important to realise is that this is bad practice in JavaScript. See the JavaScript Best Practices part to read why.
- One bug in the JavaScript Language is the famous block scoping bug. It is maybe assumed that each function gets its own block scope. Unfortunately, this is not the case:
function setLevel(level) {
this.level = level; //this now refers to the global window object
console.log(this) //Window
}
What matters is the call-site
. HOW is the function called and in what context.
WIP:
- The order of the bindings.
var team = {
names: getNames,
positions: getPositions
}
function getNames() {
var names = 'hi';
return names;
}
function getPositions() {
return positions;
}
team.names() // Refers to the team object.
team.position() // Refers to the team object.
const divineBeast = {
names: ['Ruta', 'Medoh', 'Rudania', 'Naboris'],
destroyBeasts: destroyBeasts
}
function destroyBeasts(index) {
var names = this.names;
names = names.slice(index);
this.names = names;
}
destroyBeasts.call(divineBeast, 2); // Rudania, Naboris
A list of specific JavaScript-related best practices. Best practices as 'clear variable/function names' or 'commenting your code' are not listed here since I think they're general best practices across programming.
The evilness of eval()
and with
Scoping your code
The prototype
is a property of any object that links to the object function
that constructed a new object
.
- Creates a brand new empty object when calling
new(
. - Newly created object gets linked to another object.
- Newly created objects gets passed in as the
this
context to the function. (implicit binding!) - If that function does not return its own object, the
new
return assumes you meant return that object that is passed in.
Imperative: How to accomplish a task. Doing what you told the program to do:
javascript var switchOne = 1;
The program is simply instructed to switch switchOne
on.
Declarative: What should happen?
Storing data in memory to later access them in your app, is done with variables. In ES6, const
and let
are used.
Differences with const
and let
over var
.
The JavaScript interpreter yells at you if the variables already have been declared, when trying to overwrite const
or let
variables:
// Not possible:
const level = 'Click Clock Wood';
const level = 'Bubblegloop Swamp';
Contrary to var
, let
and const
can be scoped if
blocks or regular blocks.
var
will only have localness in function blocks, and will be accessible in the global scope when used in if
blocks or regular blocks.
// var and const/let are not available outside the function block.
function setCharacter() {
var characterName = 'Kazooie';
const animal = 'Breegull';
}
// var IS visible outside the block. However const and let aren't.
{
var characterName = 'Kazooie';
const animal = 'Breegull';
}
// var IS visible outside the block. However const and let aren't.
if (game) {
var characterName = 'Kazooie';
const animal = 'Breegull';
}
const
is meant to declare constant values, values that never change. If you try to change the const
variable, the JavaScript interpreter will yell at you once again, because reassigning const
is not allowed. The following example illustrates this:
// Not working:
const tryUpdatingMe = "I can't be changed.";
tryUpdatingMe = "Another value';
To update variables , use let
.
However, properties of objects that are assigned by const
, can be updated.
const game = {
name: 'Banjo-Kazooie',
characterList: ['Grublin', 'Snacker', 'Sharpnell', 'Gruntilda', 'Mumbo Jumbo', 'Jinjonator']
}
// re-assignment of const variable like this is not possible
game = 'Mario Kart 64';
// This is possible.
game.characterList.push('Sir Slush');
// This is possible aswell.
game.name = 'The Legend of Zelda: Ocarina of Time';