Exerciții
Hoisting
function mul(a, b) {
return a * b;
}
var b;
console.log('mul', mul(2, 4));
console.log('sum', sum(2, 4));
console.log('a', a);
console.log('b', b);
let a = 10;
b = 20;
let sum = function (a, b) {
return a + b;
};
Function as value
function mul(a, b) {
return a * b;
};
let sum = function (a, b) {
return a + b;
};
let doMath = function () {
return sum;
}
console.log(
doMath()(1, 2)
);
Closure
let sum = function (a) {
return function (b) {
return a + b;
};
};
let sum5 = sum(5)
let sum10 = sum(10)
let sum2132 = sum(2132)
console.log(
sum5(10),
sum10(12),
sum2132(3),
sum5(11)
);
let ourObj = {
firstColor: 'red',
secondColor: 'black',
handleClick: function(event) {
if (event.target.style.color === firstColor) {
event.target.style.color = this.secondColor;
} else {
event.target.style.color = this.firstColor;
}
}
}
document.querySelector('h1').onclick = ourObj.handleClick.bind(ourObj)
// browser will do this:
// let event = { target: {...}, ... }
// referintaLaH1CreataDeBrowser.onclick.call(referintaLaH1CreataDeBrowser, event)
Exemplu obiecte
const oCutie = ['a', 'b', 'c'];
const oCutie = {
key: 'value',
1: 'un pix',
b: 'o foaie',
c: 90,
'': 'fara valoare',
'% - 3': '2',
};
for (var i in oCutie) {
console.log(i, oCutie[i]);
}
Calculator avansat
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Un calculator avansat</title>
<style>
/* vom folosi width fix și margin auto pentru a centra elementul în pagină*/
.calc {
width: 100px;
margin: 0 auto;
}
.display {
width: 100%;
}
/* folosim flex pentru a avea butoanele în formă de grid */
.buttons {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
</style>
</head>
<body>
<h1>Calculator</h1>
<div class="calc">
<input class="display"/>
<div class="buttons">
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
<button>6</button>
<button>7</button>
<button>8</button>
<button>9</button>
<button>0</button>
<button>+</button>
<button>-</button>
<button>=</button>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
// vom păstra referințele către elementele din DOM într-un obiect
const refs = {
// querySelector va întoarce primul element găsit în pagină
calc: document.querySelector('.calc'),
display: document.querySelector('.display'),
buttons: document.querySelector('.buttons'),
// querySelectorAll va întoarce toate elementele găsite în pagină
allButtons: document.querySelectorAll('.buttons button')
}
// elmentul .display va afișa 2 ecrane, unul e cel inițial, al doilea apare
// după ce utilizatorul a ales o operație. Vom stoca primul operand în value
// și al doilea în secondValue. în lastOp vom păstra o funcție cu operatorul
// în sine.
let value = 0;
let secondValue = 0;
let lastOp = false;
// definim funcțiile pentru operatori, le vom salva în lastOp mai apoi
const sum = function() {
return value + secondValue;
}
const dif = function() {
return value - secondValue;
}
// funcția ce va modifica valoarea corespunzătoare când utilizatorul scrie
// ceva în .display
const handleChange = function(event) {
// lastOp poate fi false sau referința către o funcție, ceea ce ne zice
// dacă trebuie să modificăm prima valoare sau a doua
if (lastOp) {
// + e folosit ca și operator unar pentru a converti un string în număr
secondValue = +event.target.value;
} else {
// event vine din DOM, și conține informații despre evenimentul pe care îl
// urmărim, în cazul nostru 'onChange', adică, atunci când utilizatorul
// scrie sau șterge în input.
// event.target este elementul care a declanșat evenimentul, în cazul
// acesta este inputul .display
// event.target.value conține valoarea unui input, în cazul nostru aici
// vom găsi ultima modificare făcută de utilizator
value = +event.target.value;
}
}
// funcția ce ascultă atunci când utilizatorul apasă pe unul din butoane
const handleClick = function(event) {
// event.target va fi butonul pe care utilizatorul a dat click
// innerText este conținutul unui element html fără html, doar textul. în
// cazul nostru va fi o cifră, +, - sau = (deoarece aceasta am scris în html)
let op = event.target.innerText;
switch(op) {
// prima oară verificăm dacă nu cumva utilizatorul a apăsat pe una din
// operații, și dacă da, vom salva în lastOp referința către funcția
// corespunzătoare
case '+': // if (op === '+')
lastOp = sum; // atenție, salvăm referința funcției (nu o apelăm)
break;
case '-':
lastOp = dif;
break;
// dacă avem = trebuie să facem calculul
case '=':
// mai întâi ne asigurăm că suntem la pasul 2
if (lastOp) {
// acum e timpul să apelăm funcția ce va face calculul
value = lastOp();
// ștergem valoarea din secondValue
secondValue = 0;
// afișăm în .display rezultatul
refs.display.value = value;
// resetăm lastOp
lastOp = false;
}
break;
default:
// parseInt va transforma un string într-un număr
op = parseInt(op);
if (lastOp) {
// înmulțim cu 10 și adunăm cifra pe care s-a apăsat, practic
// concatenăm cifra introdusă la valoarea existentă
secondValue = secondValue * 10 + op;
// afișăm noua valoare
refs.display.value = secondValue;
} else {
value = value * 10 + op;
refs.display.value = value;
}
}
}
// vom atașa funcția de handleChange la evenimentul de change, după care
// browserul ne va apela funcția noastră cu paramentrul event
// addEventListener e o formă elegantă de a scrie
// refs.display.onchange = handleChange;
refs.display.addEventListener('change', handleChange);
// fiindcă avem mai multe butoane, nu putem pune un listener direct pe ele
// una din soluții este să facem o buclă și să adăugăm un listener pe fiecare
// buton în parte (unul câte unul)
for (let i in refs.allButtons) {
// fiindcă allButtons conține un array cu toate butoanele și are proprietatea
// length, vom folosi hasOwnProperty(key) pentru a ne asigura că adăugăm un
// listener doar pe butoane, nu și pe length (vom primi eroare altfel, length
// fiind un număr)
// hasOwnProperty există pe toate obiectele din JS
if (!refs.allButtons.hasOwnProperty(i)) {
continue;
}
refs.allButtons[i].addEventListener('click', handleClick);
}