JavaScript Course 1: Basics: Difference between revisions

From WikiMLT
m (Стадий: 6 [Фаза:Утвърждаване, Статус:Утвърден]; Категория:JavaScript)
 
m (Text replacement - "mlw-continue" to "code-continue")
 
Line 21: Line 21:


Define multiple variables or constants:
Define multiple variables or constants:
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
let firstName, lastName;
let firstName, lastName;
let firstName = 'Spas', lastName = 'Spasov';
let firstName = 'Spas', lastName = 'Spasov';
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
// Best practice is to declare each variable separately:
// Best practice is to declare each variable separately:
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
let firstName = 'Spas';
let firstName = 'Spas';
let lastName = 'Spasov';
let lastName = 'Spasov';
Line 62: Line 62:


=== Issue 1 ===
=== Issue 1 ===
The first issue with <code class="noTypo">var</code> is that, it creates function scope, while <code>let</code> (and <code>const</code>) creates block scope. So the variables created by <code>var</code> can be accessed outside of the scope where they are defined.<syntaxhighlight lang="javascript" class="mlw-continue">
The first issue with <code class="noTypo">var</code> is that, it creates function scope, while <code>let</code> (and <code>const</code>) creates block scope. So the variables created by <code>var</code> can be accessed outside of the scope where they are defined.<syntaxhighlight lang="javascript" class="code-continue">
function start() {
function start() {
     for (let i = 0; i < 2; i++)
     for (let i = 0; i < 2; i++)
Line 69: Line 69:
     console.log(i);
     console.log(i);
}
}
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
start();
start();
</syntaxhighlight><syntaxhighlight lang="shell-session" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="shell-session" class="code-continue">
0
0
1
1
Line 78: Line 78:
     at start (<anonymous>:5:17)
     at start (<anonymous>:5:17)
     at <anonymous>:1:1
     at <anonymous>:1:1
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
function start() {
function start() {
     for (var i = 0; i < 2; i++)
     for (var i = 0; i < 2; i++)
Line 85: Line 85:
     console.log(i);
     console.log(i);
}
}
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
start();  // In the output below you can see the 'var i' is not terminated when the 'for(...){...}'' block is finished
start();  // In the output below you can see the 'var i' is not terminated when the 'for(...){...}'' block is finished
</syntaxhighlight><syntaxhighlight lang="shell-session">
</syntaxhighlight><syntaxhighlight lang="shell-session">
Line 91: Line 91:
1
1
2
2
</syntaxhighlight>Another example how <code>var</code> is accessible from outside the block where it is defined.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Another example how <code>var</code> is accessible from outside the block where it is defined.<syntaxhighlight lang="javascript" class="code-continue">
function start() {
function start() {
     for (let i = 0; i < 5; i++) {
     for (let i = 0; i < 5; i++) {
Line 102: Line 102:
}
}
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
start();
start();
</syntaxhighlight>
</syntaxhighlight>
Line 114: Line 114:
The second issue with <code>var</code> is related to the Global and the Local Scope - the variables, defined by <code>var</code> are attached to the <code>window</code> object (used by the browsers at the frontend).
The second issue with <code>var</code> is related to the Global and the Local Scope - the variables, defined by <code>var</code> are attached to the <code>window</code> object (used by the browsers at the frontend).


<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
var firstName = 'John';
var firstName = 'John';
let lastName = 'Smith';
let lastName = 'Smith';
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
console.log(window.firstName, window.lastName);
console.log(window.firstName, window.lastName);
</syntaxhighlight>
</syntaxhighlight>
Line 180: Line 180:


</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
let person = {
let person = {
     "name": "Spas",
     "name": "Spas",
Line 186: Line 186:
};
};
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
console.log(person);
console.log(person);
</syntaxhighlight>
</syntaxhighlight>
Line 197: Line 197:
* '''Bracket notation:''' <code class="noTypo">object['proprtyName']</code>
* '''Bracket notation:''' <code class="noTypo">object['proprtyName']</code>


<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
person.name = "Ivan";  // Assing a value to an object property via Dot notatin
person.name = "Ivan";  // Assing a value to an object property via Dot notatin
person['age'] =  25;    // Assing a value to an object property via Bracket notatin
person['age'] =  25;    // Assing a value to an object property via Bracket notatin
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
console.log(person);
console.log(person);
</syntaxhighlight>
</syntaxhighlight>
Line 207: Line 207:
{name: "Ivan", age: 25}
{name: "Ivan", age: 25}


</syntaxhighlight>Using ''Dot'' notation is cleaner and easier, but the ''Bracket'' notation could be used when we want to pass variable in the place of the key - i.e. when when using a loop or so.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Using ''Dot'' notation is cleaner and easier, but the ''Bracket'' notation could be used when we want to pass variable in the place of the key - i.e. when when using a loop or so.<syntaxhighlight lang="javascript" class="code-continue">
let keyToPrint = 'name';
let keyToPrint = 'name';
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
console.log(person[keyToPrint]);
console.log(person[keyToPrint]);
</syntaxhighlight>
</syntaxhighlight>
Line 227: Line 227:
let selectedItems = ['red', 'blue'];
let selectedItems = ['red', 'blue'];
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
console.log(selectedItems);
console.log(selectedItems);
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="shell-session">
<syntaxhighlight lang="shell-session">
(2) ["red", "blue"]
(2) ["red", "blue"]
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
console.log(selectedItems.length)
console.log(selectedItems.length)
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="shell-session">
<syntaxhighlight lang="shell-session">
2
2
</syntaxhighlight>Each element of an Array has an Index. The '''Array Index''' starts from <code>0</code>. So the first element has index <code>0</code>, the second element has index <code>1</code> and so on.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Each element of an Array has an Index. The '''Array Index''' starts from <code>0</code>. So the first element has index <code>0</code>, the second element has index <code>1</code> and so on.<syntaxhighlight lang="javascript" class="code-continue">
console.log(selectedItems[0], selectedItems[1]);
console.log(selectedItems[0], selectedItems[1]);
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="shell-session">
<syntaxhighlight lang="shell-session">
red blue
red blue
</syntaxhighlight>The JavaScript Array length is dynamic - we can change it. We can create a new index element and assign a value in the following way:<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>The JavaScript Array length is dynamic - we can change it. We can create a new index element and assign a value in the following way:<syntaxhighlight lang="javascript" class="code-continue">
selectedItems[2] = 'green'; // String
selectedItems[2] = 'green'; // String
selectedItems[3] = 33;      // Number
selectedItems[3] = 33;      // Number
selectedItems[4] = {};      // Object
selectedItems[4] = {};      // Object
</syntaxhighlight>Note in this example we have mixed the element types.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>Note in this example we have mixed the element types.<syntaxhighlight lang="javascript" class="code-continue">
console.log(selectedItems);
console.log(selectedItems);
</syntaxhighlight>
</syntaxhighlight>
Line 264: Line 264:
     console.log('Hello ' + name);
     console.log('Hello ' + name);
}
}
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
greet('Nik');        // 'Nik' is an argument which become a value of the param. 'name'
greet('Nik');        // 'Nik' is an argument which become a value of the param. 'name'
</syntaxhighlight>
</syntaxhighlight>
Line 273: Line 273:
     return number * number;
     return number * number;
}
}
</syntaxhighlight>The returned value could be assigned to a variable or object property.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>The returned value could be assigned to a variable or object property.<syntaxhighlight lang="javascript" class="code-continue">
let result = square(2);
let result = square(2);
console.log(result);
console.log(result);
Line 279: Line 279:
<syntaxhighlight lang="shell-session">
<syntaxhighlight lang="shell-session">
4
4
</syntaxhighlight>'''Single responsibility principle.''' According to this principle we should have functions that are small and focused only on one thing. Let's say we have a function that calculate the average grade of a student.<syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight>'''Single responsibility principle.''' According to this principle we should have functions that are small and focused only on one thing. Let's say we have a function that calculate the average grade of a student.<syntaxhighlight lang="javascript" class="code-continue">
const marks = [80, 90, 90];
const marks = [80, 90, 90];
</syntaxhighlight>
</syntaxhighlight>
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
function calculateGrade(marks) {
function calculateGrade(marks) {
     let sum = 0;
     let sum = 0;
Line 296: Line 296:
     return 'A';
     return 'A';
}
}
</syntaxhighlight><syntaxhighlight lang="javascript" class="mlw-continue">
</syntaxhighlight><syntaxhighlight lang="javascript" class="code-continue">
console.log(calculateGrade(marks));
console.log(calculateGrade(marks));
</syntaxhighlight>
</syntaxhighlight>
Line 304: Line 304:


By applying the ''Single responsibility principle'' we will have two small functions, one generic function that will calculate the average value, and one other function that will map the result.
By applying the ''Single responsibility principle'' we will have two small functions, one generic function that will calculate the average value, and one other function that will map the result.
<syntaxhighlight lang="javascript" class="mlw-continue">
<syntaxhighlight lang="javascript" class="code-continue">
function calculateGrade(marks) {
function calculateGrade(marks) {
     let averageGrade = calculateAverage(marks);
     let averageGrade = calculateAverage(marks);

Latest revision as of 08:29, 26 September 2022

Ref­er­ences

Vari­ables and Con­stants

var variableName = '';      // Before ECMAScript 6
let variableName = '';      // After ECMAScript 6
const constName = 'ABC';    // After ECMAScript 6

Nam­ing con­ven­tions, rules:

  • Names can­not be a re­served key­word;
  • They should be mean­ing­ful;
  • Can­not start with a num­ber;
  • Can­not con­tain space or hy­phen.;
  • The names are case sen­si­tive;
  • Use camel­No­ta­tions;

De­fine mul­ti­ple vari­ables or con­stants:

let firstName, lastName;
let firstName = 'Spas', lastName = 'Spasov';
// Best practice is to declare each variable separately:
let firstName = 'Spas';
let lastName = 'Spasov';

Scope (sum­ma­ry from all parts of the course)

Read this sec­tion once again when fin­ish the course. JavaScript vari­ables can be­long to the lo­cal or glob­al scope. Glob­al vari­ables live un­til the page is dis­card­ed, like when you nav­i­gate to an­oth­er page or close the win­dow. Lo­cal vari­ables have short lives. They are cre­at­ed when the func­tion (or oth­er type of code block) is in­voked, and delet­ed when the func­tion is fin­ished.

Vari­ables cre­at­ed with­out a de­c­la­ra­tion key­word (var, let, or con­st) are al­ways glob­al, even if they are cre­at­ed in­side a func­tion (or oth­er type of code block).

A lo­cal scope is de­fined by the JavaScript el­e­ments that us­es code block – {}, like as:

  • Func­tions: func­tion() {…}
  • Loops: while() {…}, for() {…}, etc.
  • Ob­jects: con­st obj = {…}
  • If blocks: if (…) {…}
  • etc.
{
    const message = 'hi';
}
console.log(message);
Uncaught ReferenceError: message is not defined at <anonymous>:1:13

Glob­al vari­ables can be made lo­cal (pri­vate) with clo­sures.

It is bet­ter prac­tice, when it is pos­si­ble, to do not use Glob­al vari­ables.

When we have Lo­cal and Glob­al vari­ables (or con­stants) with ex­act same names – the Lo­cal vari­ables (or con­stants) take prece­dence over the glob­al vari­ables (or con­stants).

Var vs Let and Con­st (is­sues with Var)

Read this sec­tion once again when fin­ish the course.

Is­sue 1

The first is­sue with var is that, it cre­ates func­tion scope, while let (and con­st) cre­ates block scope. So the vari­ables cre­at­ed by var can be ac­cessed out­side of the scope where they are de­fined.

function start() {
    for (let i = 0; i < 2; i++)
        console.log(i);
    
    console.log(i);
}
start();
0
1
Uncaught ReferenceError: i is not defined 
    at start (<anonymous>:5:17)
    at <anonymous>:1:1
function start() {
    for (var i = 0; i < 2; i++)
        console.log(i);
    
    console.log(i);
}
start();  // In the output below you can see the 'var i' is not terminated when the 'for(...){...}'' block is finished
0
1
2

An­oth­er ex­am­ple how var is ac­ces­si­ble from out­side the block where it is de­fined.

function start() {
    for (let i = 0; i < 5; i++) {
        if (true) {
            var color = 'red';
        }
    }

    console.log(color);
}
start();
red

If we have used let color = 'red' the above code will throw an er­ror, but when we use var color = 'red' we can ac­cess the vari­able in­side the whole func­tion not on­ly with­in the if(…){…} scope.

Is­sue 2

The sec­ond is­sue with var is re­lat­ed to the Glob­al and the Lo­cal Scope – the vari­ables, de­fined by var are at­tached to the win­dow ob­ject (used by the browsers at the fron­tend).

var firstName = 'John';
let lastName = 'Smith';
console.log(window.firstName, window.lastName);
John undefined

Types

  • Prim­i­tives (val­ue types)
  • Ref­er­ence types (ob­jects, ar­rays, func­tions)

JavaScript is a dy­nam­ic lan­guage. Which means we can change the type of a vari­able dur­ing the script, un­like the sta­t­ic lan­guages where the de­fined vari­able type is con­stant and can­not be changed dur­ing the pro­gram.

Prim­i­tive types

The prim­i­tive types in JavaScript are:

  1. Strings
  2. Num­bers
  3. Booleans
  4. un­de­fined
  5. null
  6. Sym­bol
let name = 'Spas';          // String Literal
let age = 55;               // Number Literal
let isViewMode =  true;     // Boolean Literal (true/false)
let fullName = undefined;   // This is the default type of values in JavaScript
let lastName = null;
let mySymbol = Symbol('someDescription'); // Symbol value with description
A val­ue hav­ing the da­ta type Sym­bol can be called a “Sym­bol val­ue”. In a JavaScript run­time en­vi­ron­ment, a sym­bol val­ue is cre­at­ed by call­ing the glob­al func­tion Sym­bol(), which dy­nam­i­cal­ly pro­duces an anony­mous, unique val­ue. A sym­bol can be used as an ob­ject prop­er­ty. Sym­bol is not a full con­struc­tor. No­tice that there was no new Key­word. As Sym­bol is a prim­i­tive val­ue, if we at­tempt to cre­ate a sym­bol us­ing the new op­er­a­tor, the new op­er­a­tor throws a Type­Er­ror. We can pass a pa­ra­me­ter to Sym­bol(), and that is used as the sym­bol de­scrip­tion, use­ful just for de­bug­ging pur­pos­es.

The Num­bers could be in­te­ger or float­ing point num­bers, but their types are all num­bers.

let integer = 12;
typeof integer;   // "number"
let floating = 1.2;
typeof floating;  // "number"

Ref­er­ence types

The ref­er­ence types in JavaScript are:

  1. Ob­jects
  2. Ar­rays
  3. Func­tions

Ob­jects

The Ob­jects has:

  • Prop­er­ties – prim­i­tives de­fined by "keys": and "values",
  • Meth­ods – in­ter­nal functions() that op­er­ates with the prop­er­ties of the ob­ject.
let person = {};    // Object Literal
typeof person;      // "object"
let person = {
    "name": "Spas",
    "age":  55
};
console.log(person);
{name: "Spas", age: 55}

We can ac­cess the Prop­er­ties of an Ob­ject via:

  • Dot no­ta­tion: object.proprtyName
  • Brack­et no­ta­tion: object['proprtyName']
person.name = "Ivan";   // Assing a value to an object property via Dot notatin
person['age'] =  25;    // Assing a value to an object property via Bracket notatin
console.log(person);
{name: "Ivan", age: 25}

Us­ing Dot no­ta­tion is clean­er and eas­i­er, but the Brack­et no­ta­tion could be used when we want to pass vari­able in the place of the key – i.e. when when us­ing a loop or so.

let keyToPrint = 'name';
console.log(person[keyToPrint]);
Ivan

Ar­rays

JavaScript Ar­ray is a da­ta struc­ture that we use to rep­re­sent a list of items, in this count an item could be Prim­i­tives or Ob­jects. JavaScript Ar­rays can­not be mul­ti di­men­sion­al, but the can store Ob­jects in­stead Prim­i­tives – and can mix them.

let selectedItems = []; // Array Literal
typeof selectedItems;   // "object"

The JavaScript Ar­ray is (a kind of) Ob­ject and it has prop­er­ties and meth­ods (in­her­it­ed from its Pro­to­type). See the selectedItems.lenght ex­am­ple be­low.

let selectedItems = ['red', 'blue'];
console.log(selectedItems);
(2) ["red", "blue"]
console.log(selectedItems.length)
2

Each el­e­ment of an Ar­ray has an In­dex. The Ar­ray In­dex starts from 0. So the first el­e­ment has in­dex 0, the sec­ond el­e­ment has in­dex 1 and so on.

console.log(selectedItems[0], selectedItems[1]);
red blue

The JavaScript Ar­ray length is dy­nam­ic – we can change it. We can cre­ate a new in­dex el­e­ment and as­sign a val­ue in the fol­low­ing way:

selectedItems[2] = 'green'; // String
selectedItems[3] = 33;      // Number
selectedItems[4] = {};      // Object

Note in this ex­am­ple we have mixed the el­e­ment types.

console.log(selectedItems);
(5) ["red", "blue", "green", 33, {…}]

Func­tions

JavaScript Func­tions are sets of state­ments that per­forms a task or cal­cu­lates a val­ue. The Func­tions could have In­puts – could use (mul­ti­ple) pa­ra­me­ters – but it is not manda­to­ry.

function greet(parameter) {
    /** Body of the function **/
}
typeof greet;   // "function"
function greet(name) {   // 'name' is an input parameter of the function
    console.log('Hello ' + name);
}
greet('Nik');         // 'Nik' is an argument which become a value of the param. 'name'
Hello Nik

The func­tions could Change the val­ues of a glob­al vari­ables (ob­jects) or could Re­turn a val­ue.

function square(number) {
    return number * number;
}

The re­turned val­ue could be as­signed to a vari­able or ob­ject prop­er­ty.

let result = square(2);
console.log(result);
4

Sin­gle re­spon­si­bil­i­ty prin­ci­ple. Ac­cord­ing to this prin­ci­ple we should have func­tions that are small and fo­cused on­ly on one thing. Let's say we have a func­tion that cal­cu­late the av­er­age grade of a stu­dent.

const marks = [80, 90, 90];
function calculateGrade(marks) {
    let sum = 0;

    for (let mark of marks) sum += mark;
    
    let averageGrade = sum / marks.length;

    if (averageGrade < 60) return 'F';
    if (averageGrade < 70) return 'D';
    if (averageGrade < 80) return 'C';
    if (averageGrade < 90) return 'B';
    return 'A';
}
console.log(calculateGrade(marks));
B

By ap­ply­ing the Sin­gle re­spon­si­bil­i­ty prin­ci­ple we will have two small func­tions, one gener­ic func­tion that will cal­cu­late the av­er­age val­ue, and one oth­er func­tion that will map the re­sult.

function calculateGrade(marks) {
    let averageGrade = calculateAverage(marks);

    if (averageGrade < 60) return 'F';
    if (averageGrade < 70) return 'D';
    if (averageGrade < 80) return 'C';
    if (averageGrade < 90) return 'B';
    return 'A';
}

function calculateAverage(array) {
    let sum = 0;
    for (let value of array) sum += value;
   
    return sum / array.length;
}

Read al­so:

Garbage Col­lec­tor

In low lev­el lan­guages like C or C++, when cre­at­ing an ob­ject we need to al­lo­cate mem­o­ry to it, and when we're done we have to deal­lo­cate mem­o­ry. But in JavaScript we don't have this con­cept. We can eas­i­ly cre­ate a new ob­ject. At the time we ini­tial­ize this ob­ject, then mem­o­ry is au­to­mat­i­cal­ly al­lo­cat­ed to this ob­ject. Next, we can use that. And when we were done us­ing, we don't have to deal­lo­cate the mem­o­ry. So the JavaScript en­gine has what we call a garbage col­lec­tor.

The job of the garbage col­lec­tor is to find the vari­ables or con­stants that are no longer used and then deal­lo­cate the mem­o­ry that was al­lo­cat­ed to them ear­li­er. So you as a JavaScript de­vel­op­er do not have to wor­ry about this mem­o­ry al­lo­ca­tion. And the al­lo­ca­tion hap­pens au­to­mat­i­cal­ly be­hind the scene and you have no con­trol over that.

You can­not tell the garbage col­lec­tor when to run and what vari­ables to re­move from the mem­o­ry. So based on some com­plex al­go­rithms, this garbage col­lec­tor runs in the back­ground. It fig­ures out what vari­ables are not used and then it will au­to­mat­i­cal­ly deal­lo­cate their mem­o­ry.