------------------------------------------ https://codepen.io/login marc.houben@planet.nl j6UmHBCR codepen.io/houbenm https://jsfiddle.net/user/login/ houbenm j6UmHBCR Chrome DevTools ( Control+Shift+C of Control+Shift+J ) When you want to work with the DOM or CSS, right-click an element on the page and select Inspect to jump into the Elements panel. Or press Command+Option+C (Mac) or Control+Shift+C (Windows, Linux, Chrome OS). When you want to see logged messages or run JavaScript, press Command+Option+J (Mac) or Control+Shift+J (Windows, Linux, Chrome OS) to jump straight into the Console panel. ------------------------------------------ Een verwijzing naar een extern bestand gebeurt met . Tussen beide tags staat dan geen code. In het externe bestand staat alleen de javascript code, dus daar ontbreken de geplaatst. Statements zijn gehele commando regels JavaScript waarin, bijvoorbeeld, een berekening wordt uitgevoerd en het resultaat wordt getoond op het scherm. Een statement kan bestaan uit een zogeheten toekenning. Daarbij wordt bijvoorbeeld: Een DIV element uit de HTML structuur opgezocht Een tekst wordt in dit element gezet (toekenning, met behulp van een = teken). // 02 - Eenvoudig beginnen console.clear(); var a = 13; var b = 2.5; // voorbeeld van optelling //alert( a + b); console.log(a + b); // voorbeeld gevaar optelling met string console.log("som: " + a + b); // voorbeeld met haakjes: console.log("som: " + (a + b)); // voorbeeld octaal: console.log(parseInt("15",8)); // 5*8**0 + 1*8**1 = 13 Met een dubbele slash // kunnen we commentaar in een stuk JavaScript code plaatsen. Dit zorgt ervoor dat de code die erachter staat niet wordt uitgevoerd. Dit kunnen we ook doen met een slash en sterretje aan het begin en een (omgekeerde volgorde dus) sterretje en slash aan het einde. Bij de eerste mogelijkheid kan commentaar op een regel worden opgenomen. De andere mogelijkheden worden gebruikt om commentaar over meerdere regels op te nemen. Bij de eerste twee manieren wordt de code altijd genegeerd, bij de derde en vierde mogelijkheid hangt van van de browser(versie) af. Bij de eerste mogelijkheid kan commentaar op een regel worden opgenomen. De andere mogelijkheden wordt gebruikt om commentaar over meerdere regels op te nemen. Bij de eerste twee manieren wordt de code altijd genegeerd, bij de derde en vierde mogelijkheid hangt van van de browser(versie) af. De mogelijkheid -- uit de vraag is in veel talen geschikt om commentaar op te nemen, maar niet in javascript. Javascript in HTML pagina Javascript in extern bestand Datatypen We hebben al geleerd wat een variabele is, hoe we die kunnen aanmaken en hoe we ermee kunnen werken. Nu gaan wij hier dieper op in en leren we welke soorten gegevens wij in een variabele kwijt kunnen. Er bestaan twee groepen datatypen: primitieve datatypen (immutable) boolean (true of false) null type (intentionele afwezigheid van een waarde) undefined (nog geen waarde toegekend) number (64 bits floating point), zoals: +0, -0, NaN (not a number), -Infinity, +Infinity, 2, 20.3 string: tekstwaarden tussen enkele of tussen dubbele quotes complexe datatypes: arrays objecten functies Hieronder worden deze datatypen kort toegelicht met behulp van code. In de loop van deze cursus zullen we er uitvoeriger op ingaan. De volgende code illustreert het datatype number. var x = 3; var y; console.log(y); // undefined console.log(x/y); // NaN y=null; console.log(x/y); // delen door null: Infinity y=-0; console.log(x/y); // delen door -0: -Infinity y = "test"; console.log(x/y); // delen door tekst: NaN Number.isInteger(x); // true y = Number.parseFloat("2.5.9"); // Zet tekst om naar een gebroken getal console.log(y); // 2.5 y = Number.parseInt("2.5.9"); // Zet tekst om naar een geheel getal console.log(y); // 2 De volgende code illustreert het datatype String. Dat is een waarde tussen " en ", of tussen ' en ', of tussen ` en ` . Het laatste geval wordt een template literal genoemd, nieuw vanaf EcmaScript 2015. Hierin kun je de inhoud van variabelen uitlezen door ze tussen accolades te plaatsen met een dollar teken ervoor, zie de code. var naam = window.prompt("Geef uw naam op: "); var tekst = "Wij hopen dat het u " + "goed zal bevallen."; var alternatief = "Wij hopen dat het u \ goed zal bevallen."; var boodschap = `Welkom op deze cursus, ${naam}. ${tekst}`; console.log(boodschap); Uitvoer, bijvoorbeeld: Welkom op deze cursus, Heleen. Wij hopen dat het u goed zal bevallen. Een Array is een verzameling waarden. Deze wordt aangemaakt door de waarden met komma's gescheiden tussen [ en ] te plaatsen. Een waarde kan uit zo'n verzameling worden gehaald met de index. Het eerste element heeft dan de index 0. var fruit = ["appels", "peren", "bananen"]; console.log(fruit[1]); // uitvoer: peren fruit[0]="aardbeien"; fruit[3]="kersen"; // nieuwe waarde console.log(fruit); // uitvoer: ["aardbeien", "peren", "bananen", "kersen"] Een object is een verzameling eigenschappen met waarden. De eenvoudigste manier om zo'n object aan te maken is eigenschap-waarde paren met komma's gescheiden te plaatsen tussen { en }. Tussen de eigenschap en de waarde staat een dubbele punt. Het volgende voorbeeld laat daar een relatief eenvoudig voorbeeld van zien. Merk op dat een eigenschap uit zo'n object kan worden uitgelezen met . var artikel = { naam: "pen", prijs: 1.5 }; console.log(artikel.naam); // uitvoer: pen artikel.prijs = 1.6; console.log(artikel.prijs); // uitvoer: 1.6 Een functie is een programma met een naam, mogelijk met invoer en/of uitvoer. Het volgende voorbeeld toont een functie die som kan berekenen tussen twee opgegeven waarden. We komen hier later uitvoerig op terug. function som(a, b) { var uitkomst = a + b; return uitkomst; } var x = som(3,4); console.log(x); // uitkomst: 7 Variabelen worden in JavaScript, in tegenstelling tot veel programmeertalen, niet gedeclareerd. Er wordt dus niet van tevoren vastgelegd welke datatypen we in de variabelen kunnen opslaan. We kunnen dus zonder problemen de waarde van een variabelen veranderen in een waarde van een ander datatype. JavaScript heeft zes primitieve datatypen: Boolean, Null,,,Undefined, Number, String en Symbol (nieuw in ECMAScript 6). Daarnaast zijn er complexe datatypen (object). De console Bij het ontwikkelen in Javascript is het verstandig om regelmatig te controleren of alles werkt zoals verwacht. Als hulpmiddel kunnen waarden van variabelen naar de console worden weggeschreven: dit is het deel van de browser die normaal gesproken onzichtbaar is, maar tijdens het ontwikkelen kan worden geopend. Chrome, Firefox, Internet Explorer en andere browsers hebben allemaal iets vergelijkbaars als Developer Tools in het menu staan. Een onderdeel daarvan is de console. De functie log van console kan de waarde van één of meer variabelen tonen. Bijvoorbeeld: var x = 1; var y = 2; var som = x + y; console.log(som) ; // 3 console.log(x, y, som); // 1 2 3 Het kan ook handig zijn om de console weer even leeg te maken. Als we dat bovenaan het scherm doen, zal de console leeg worden gemaakt voor elke verversing van de pagina: console.clear(); Vaak is het ook handig om meerdere bij elkaar horende statements te groeperen, om overzicht te houden wat waarbij hoort. console.clear(); console.group("optelling"); var x = 2; var y = 3; var som = x + y; console.log("x = ", x) ; console.log("y = ", y); console.log("totaal:", som); console.groupEnd(); Scope De bereikbaarheid van variabelen is een zeer belangrijk onderdeel van goed kunnen programmeren in JavaScript. De waarde van een variabele is bij het aanmaken alleen bekend binnen de functie waarin hij is aangemaakt. Een functie is een blok code met accolades er omheen en een naam, zodat we later kunnen terug verwijzen naar dat blok. Indien een variabele niet binnen een functie is aangemaakt, zal hij onderdeel zijn van de zogeheten globale scope. var globaal = "ik ben overal bekend"; function besloten() { var lokaal = "ik ben alleen in deze functie bekend"; } // We proberen nu de waarde van de globale variabele te tonen: console.log(globaal); // We proberen nu de waarde van de lokale variabele te tonen: console.log(lokaal); // Zoals je kunt zien in de console.log () krijgen we de fout: // 'Uncaught ReferenceError: lokaal is not defined' // Indien een variabele wél binnen bereik (scope) is, maar niet gevuld is, krijgen wij geen foutmelding maar is de variabele 'undefined' var leeg; console.log(leeg); Let en const Sinds de ontwikkeling van de ES6 standaard, kennen we het 'let' sleutelwoord. Daarmee kunnen wij ook variabelen declareren, dus net zoals met het 'var' sleutelwoord. Het verschil is dat een variabele die is aangemaakt (gedeclareerd is, eventueel nog zonder waarde) met het 'let' sleutelwoord, zogeheten 'block scope' heeft: deze is alleen bekend binnen het block waarin de variabele is aangemaakt. Voorbeeld met var: for(var x = 1;x<10;x++){ // doe iets met x } console.log(x); // 10! Voorbeeld met let: for(let y = 1;y<10;y++){ // doe iets met y } console.log(y); // Error: y is not defined Sinds ES6 kennen we ook de term 'const' hiermee maken wij variabelen aan met een constante waarde, de waarde van die variabele mag dus niet aangepast worden. Let op: indien wij een zogeheten 'object' in een variabele plaatsen, mag dat object zelf wél gewijzigd worden. Voorbeeld zonder het let statement: (function beperkt() { // Onderstaande code is een 'for-loop' deze stof hoeven wij nog niet te kennen. // Belangrijk is dat de waarde van de onderstaande 'teller' // te gebruiken is -buiten- de loop. Dit is in vele andere programmeertalen // -niet- het geval en is vaak ook onpraktisch: for (var teller=0; teller<10; teller++) { console.log("Nog een keer door de loop"); } teller = teller+1; console.log("Waarde van teller is:" + teller); // We zien dat teller op 11 staat. Dit komt doordat een variabele // in JavaScript 'function scope' heeft, ofwel; binnen de hele // functie te gebruiken. })(); En een voorbeeld met het let statement: (function beperkt() { // Doordat wij nu het keyword 'let' gebruiken in onderstaande 'loop', // blijft de scope van de teller variabele -binnen- de loop for (let teller=0; teller<10; teller++) { console.log("Nog een keer door de loop"); } teller = teller+1; console.log("Waarde van teller is:" + teller); // We zien in de log een fout op bovenstaande twee regels: // 'Uncaught ReferenceError: teller is not defined' })(); Hoisting JavaScript is een eigenaardige taal wanneer het gaat om declaratie van variabelen en functies. Variabele declaraties én functie declaraties (komt later aan bod) worden automatisch naar boven geplaatst bij het uitvoeren van een pagina. Hier kun je soms iets van merken. Let op dat dit niet gaat om variabele initialisaties (dus het vullen van een variabele). // Onderstaande gaat goed doordat JavaScript variabele declaraties naar boven verplaatst en dus eerst uitvoert. // Vullen van variabelen doet hij dan nog niet. Vandaar de melding 'undefined', in plaats van een waarde en in plaats van een foutmelding // dat de variabele niet bestaat. console.log(laterGemaakt); var laterGemaakt = "interessant"; // Onderstaande gaat (ook) goed doordat JavaScript functie declaraties ook naar boven verplaatst en dus eerst uitvoert. console.log(mooieFunctie()); function mooieFunctie() { return "Mooi he?"; } Operatoren Wat zijn operatoren precies en waarvoor gaan wij ze gebruiken? In veel programmeertalen worden operatoren gebruikt voor allerlei handelingen: Praktijk toepassingen: Waarde vergelijkingen Toekenningen van waarden Rekenkundige acties Teksten aan elkaar plakken Type vergelijkingen Hoe plakken we de inhoud van de onderstaande variabele vast aan de tekst die wij op het scherm gaan tonen? var x = 12; var tekst = 'Het maximum aantal cursisten in een klaslokaal is: ' 1) + Bekijk de onderstaande code t = 9%2; Wat is de waarde van t na het uitvoeren van deze code? Het correcte antwoord is: 1 De % operator berekent de modulus uit: het restant van een deling als alleen gehele getallen zijn toegestaan. Het hoogste getal wat deelbaar is door 2 en nog kleiner is dan 9 is 8. Het deel dat overblijft (9-8) kan niet meer door 2 worden gedeeld: dat is de modulus. In JavaScript kunnen wij op de volgende manier kijken of waarden ongelijk zijn aan elkaar: 1) <> 2) != 3) ^= Alleen 2 is juist var invoer1 = 10 var invoer2 = 20 if (invoer1 == invoer2) { alert("Invoer gelijk!"); // window.alert() mag ook } var invoer1 = 10 var invoer2 = 20 if (invoer1 == invoer2) { alert("Invoer gelijk!"); // window.alert() mag ook } else { alert("Invoer verschillend!") } De opdracht(en) na de controle van een if statement moeten we altijd tussen accolades {} opnemen wanneer het om meerdere opdrachten op verschillende regels gaat. Betreft het één opdracht dan kunnen de accolades achterwege blijven. Accolades MOETEN we binnen een if statement alleen toevoegen wanneer MEERDERE statements na controle van de conditie moeten worden uitgevoerd op verschillende regels. Anders gaat de browser er vanuit dat alleen de eerste opdracht bij het if statement behoort en niet de tweede en (eventueel) volgende statements. Bij het opnemen van een enkel statement is het niet verplicht. Onderstaande DRIE syntaxen zijn dus goed: if (contole) if (controle) statement; statement statement if (contole) {statement; statement} Accolades MOETEN we binnen een if statement alleen toevoegen wanneer MEERDERE statements na controle van de conditie moeten worden uitgevoerd, anders gaat de browser er vanuit dat alleen de eerste opdracht bij het if statement behoort en niet de tweede en (eventueel) volgende statements. Bij het opnemen van een enkel statement zijn accolades niet nodig. Onderstaande syntaxen zijn dus beide goed: if (contole) if (controle) {statement; statement} statement var geslacht = prompt("Bent u een man of een vrouw? (M/V)"); switch(geslacht.toUpperCase()){ case "M": console.log("Dag meneer"); break; case "V": console.log("Dag mevrouw"); break; default: console.log("Dag persoon"); } In onderstaand voorbeeld staat de traditionele for loop. Achter het keyword for staan drie onderdelen tussen haakjes: een startwaarde, de voorwaarde om de loop te herhalen, en een statement om de voorwaarde uiteindelijk op false uit te laten komen. Zonder dat laatste statement zou een oneindige loop kunnen ontstaan. var klassen = ["Warrior","Mage","Druid","Priest","Hunter","Bard"]; // for-loop: for (var index=0; index 10){ // Onderstaande code wordt nu NIET uitgevoerd, // immers: de i>10 conditie is false. console.log(i + " * " + x + " = " + (i * x)); i++; } console.groupEnd(); // tafel van 3 met do while lus console.group("tafel van 3 met do while loop"); var x = 3; var i = 1; do { // Onderstaande code wordt nu WEL (1x) uitgevoerd, // immers: de i>10 conditie wordt pas na het codeblok gesteld. console.log(i + " * " + x + " = " + (i * x)); i++; } while (i > 10) console.groupEnd(); We kunnen ook aan de for lus meerdere voorwaarden (en ook initialisatiewaarden en ophogingen) meegeven, gescheiden door een komma. Voorbeeld: for ( teller=1, getal=8 ; teller<=10, getal>0; teller++, getal=teller-2 ) Er zijn hier twee initialisatiewaarden, twee voorwaarde en twee ophogingen. function eenvoudig() { console.log("Dit is een eenvoudige functie"); } function returnWaarde() { var a = 10; var b = 2; return a*b; } function parameterWaarde(invoer1,invoer2) { console.log(invoer1*invoer2); } // Aanroep eerste eenvoudige functie: eenvoudig(); // Aanroep tweede functie, die waarde teruggeeft: var uitkomst = returnWaarde(); console.log("Resultaat:" + uitkomst); // Aanroep derde functie, die waarde mee krijgt: parameterWaarde(20,3); console.clear(); console.group("vier functies"); var add = function(a, b){ return a + b; }; console.log(add(3,4)); var subtract = function(a, b){ return a - b; }; console.log(subtract(3,4)); var multiply = function(a, b){ return a * b; }; console.log(multiply(3,4)); var divide = function(a, b){ if(b === 0) { throw "Delen door nul is niet toegestaan"; // het zogeheten opgooien van een fout // dit hoeven wij nog niet te kennen } else return a / b; }; console.log(divide(3,4)); // Onderstaande 'try' en 'catch' blokken hoeft u nog niet te kennen try { console.log(divide(3,0)); } catch(error){ console.log(error); } console.groupEnd(); console.group("voornaam en achternaam"); function concat(a, b){ if( typeof a == "string" && typeof b == "string" ) return a + " " + b; } var voornaam = prompt("wat is uw voornaam? "); var achternaam = prompt("wat is uw achternaam? "); console.log("Welkom " + concat(voornaam, achternaam)); console.groupEnd(); In het volgende voorbeeld gebruikten wij dit 'onload' event om met een functie de achtergrondkleur groen te maken: console.group("Anonieme functies"); window.onload=function(){ document.body.style.backgroundColor="green"; } console.groupEnd(); Het toevoegen van een return statement aan een functie is optioneel. In een functie kunnen we een parameter opnemen, als we van buiten de functie een waarde aan de functie willen meegeven. Dit is echter niet verplicht. function telop(a, b){ if(typeof a !== 'number' || typeof b!== 'number'){ throw 'foute invoer, gebruik getallen'; } return a + b; } console.log(telop('test', 4)); function telop(a, b){ if(typeof a !== 'number' || typeof b!== 'number'){ throw 'foute invoer, gebruik getallen'; } return a + b; } try { // iets wat mis kan gaan: console.log(3,4); // gaat goed console.log(telop('test', 4)); // gaat mis: spring naar catch block console.log(5,6); // wordt niet meer uitgevoerd } catch (fout){ // als er iets mis gaat: console.log("Er ging iets mis: " + fout); } function minMax(a,b){ let minWaarde = ab ? a : b; return { min: minWaarde, max: maxWaarde }; } let test = minMax(3,4); console.log(test.min); // 3 console.log(test.max); // 4 Let op: bij het return statement moet direct achter return de eerste accolade openen worden gegeven. Anders wordt automatisch een punt-komma toegevoegd achter return en wordt er dus niets geretourneerd. console.group("Anonieme functies"); window.onload=function(){ document.body.style.backgroundColor="green"; } console.groupEnd(); Er volgt nu een nog voorbeeld die gebruik maakt van een closure: var BankRekening = function(nr, sal) { var nummer = nr; var saldo = sal; return { getSaldo: function() { return saldo; // geen this, want we zitten in een object. }, getNummer: function(){ return nummer; // geen this, want we zitten in een object. } } } // de functie achter 'var BankRekening =' levert dus een object op met twee eigenschappen. var mijnRekening = new BankRekening(1234,100); console.log(mijnRekening.getSaldo()); Met een closure kun je juist specifieke code onzichtbaar maken voor de 'buiten wereld'. Wél is het vervolgens mogelijk met get en set methoden de toegankelijkheid naar de lokale variabelen te regelen. In het volgende voorbeeld maken we een IIFE aan die een object terug geeft. Hiervoor gelden dezelfde regels; lokalen variabelen in de IIFY functie zijn alleen bekend in de geneste functie of het geneste object. mijnApp = function(){ var naam; var leeftijd; return { setNaam: function(n){ naam = n; // this.naam? }, getNaam: function(){ return naam; }, setLeeftijd: function(l){ leeftijd = l; }, getLeeftijd: function(){ return leeftijd; } } }(); window.onload=function(){ console.log(mijnApp.getNaam()); mijnApp.setNaam("Gamer"); mijnApp.setLeeftijd("34"); console.log(mijnApp.getNaam()); console.log(mijnApp.getLeeftijd()); } document.getElementById("blokje").style.left = "300px"; Met callback functies kunnen we tegen een probleem qua scope aan lopen. HTML:
CSS: div { position: absolute; } Javascript: window.onload = function(){ document.body.addEventListener("keydown", function(e){ document.getElementById("blokje").style.left = "100px"; /* Het per keer verplaatsen van een element kost meer moeite, we zouden dan de huidige positie moeten ophalen en daar de tekst 'px' vanaf moeten knippen. De vervolgens wijzigen en weer 'px' toevoegen, maar ook dan zullen er de nodige haken en ogen aan de constructie zitten. */ }, true); } Een callback functie wordt gebruikt om aan te geven dat een functie aanroep op een bepaald moment, niet direct dient te gebeuren, maar op een later moment. Soms willen we aangeven dat een functie moet worden uitgevoerd als (bijvoorbeeld) een reactie op het klikken met de muisknop of als reactie op het ontvangen van een bericht middels een AJAX call. Denk aan het maken van een event listener. Daarbij mogen wij inline een stuk code plaatsen die uitgevoerd moet worden wanneer het event afgaat, máár we mogen er ook de naam van een functie in plaatsen.. ZONDER haken: (). Dat is essentieel. Arrow functions, ofwel 'fat arrows', verkorten dus drastisch de schrijfwijze van de aanroep en declaratie van een functie. Bekijk de volgende twee voorbeelden op volgorde. We kijken eerst naar een gewone anonieme functie die als parameter wordt meegegeven aan setTimeOut(): HTML: Voortgang:
Javascript: function Wijnfles() { this.aantalSlokken = 50; var zelf = this; // Voorbeeld met een bestaande functie die twee parameters aan kan: setInterval(function(){ zelf.aantalSlokken--; document.getElementsByTagName("progress")[0].value = zelf.aantalSlokken; }, 400); } var grandCru2005 = new Wijnfles(); var p1 = { naam: "Amy", leeftijd: 18, hobby: "Paard rijden", zegIets: function() { return "ik vertel graag iets over mijn hobby: " + this.hobby } }; var p2 = { naam: "Jacob", leeftijd: 20, hobby: "Rondjes rennen", zegIets: function() { return "ik vertel graag iets over mijn hobby: " + this.hobby } }; function Persoon(naam, leeftijd, hobby) { this.naam = naam; this.leeftijd = leeftijd; this.hobby = hobby; } Persoon.prototype.zegIets = function() { return "ik vertel graag iets over mijn hobby: " + this.hobby; } var p1 = new Persoon("Amy", 18, "Paard rijden"); var p2 = new Persoon("Jacob", 20, "Rondjes rennen"); We hebben kunnen zien dat we in het tweede voorbeeld compacter, maar vooral meer 'object georienteerd' aan het programmeren waren. Bij het eerste voorbeeld kan gerust een andere programmeur een persoon maken met andere eigenschappen. In voorbeeld twee zijn de eigenschappen middels een functie (wat) meer afgedwongen. Een object aanmaken hebben we gedaan door een functie aan te roepen. Deze maakte voor ons het object aan. Ook konden wij parameters (argumenten) meegeven, die dan direct aan de eigenschappen van het object werden toegekend. Daardoor was het niet nodig nog los iedere eigenschap van de instantie een waarde te geven. Tot slot is de functie 'zegIets()' bij het tweede voorbeeld effecienter qua geheugengebruik. Bij de eerste manier wordt deze functie voor ieder object apart in het geheugen gezet. Bij het tweede voorbeeld wordt de functie maar één keer opgeslagen en door meedere objecten gebruikt. Er volgt nu een voorbeeld over het gebruik van een prototype functie: var Speler = function(leven, mana, wapensoort) { this.levenspunten = leven; this.manapunten = mana; this.wapen = wapensoort; this.aanvalskracht = (this.levenspunten + this.manapunten) / 2; } /* Door onderstaande functie niet in bovenstaande constructor te verwerken, wordt er één functie gemaakt die wordt toegepast op alle Speler objecten, in plaats van één functie PER Speler object */ Speler.prototype.valAan = function(vijand) { vijand.levenspunten -= this.aanvalskracht; console.log("Aangevallen. Tegenstander heeft nog: " + vijand.levenspunten + " levenspunten"); } var mage = new Speler(20,100,"wand"); var warrior = new Speler(100,30,"zwaard"); warrior.valAan(mage); De prototype notatie zorgt er -juist- voor dat deze functie gedeeld wordt in het geheugen met andere objecten. Met prototype kan men bij aan een (eventueel zelf aangemaakt) object, zelf aangemaakte eigenschappen koppelen. Dit vereenvoudigt het object-georiënteerd werken. Met PROTOTYPE kan men het toevoegen van zelf gemaakte eigenschappen aan objecten vereenvoudigen. Met de call en apply functies kunnen wij een reeds bestaande functie toepassen op een ander (dan origineel) object. De call methode accepteert (indien gewenst en náást het object dat gebruikt wordt als waarde voor 'this') ook -losse- parameters, die als input parameters voor de toe te passen functie gebruikt zullen worden. class Tafel { static aantal = 0; constructor(lengte, breedte, kleur, prijs){ this.lengte = lengte; this.breedte = breedte; this.kleur = kleur; this.prijs = prijs; Tafel.aantal++; console.log(`Tafel gemaakt, er zijn nu ${Tafel.aantal} tafel(s)`); } verkoop(){ console.log('Verkoop start...'); Tafel.aantal--; console.log(`Verkocht! Huidige voorraad van tafels is: ${Tafel.aantal}`); } verf(kleur) { this.kleur = kleur; console.log(`Tafel is nu ${this.kleur} geverfd`); } } let t1 = new Tafel(200, 90, "oud eiken bruin", 500); t1.verf("geel"); t1.verkoop(); let t2 = new Tafel(100,100, "meranti donker bruin", 1200); let t3 = new Tafel(150,70, "esdoorn met knoesten", 1500); t2.verkoop(); Een mooie feature die JavaScript nog nét iets meer object georiënteerd maakt, is de mogelijkheid subklassen te maken. Ofwel: klassen te laten overerven van andere klassen. Bekijk het volgende voorbeeld: class Tafel { static aantal = 0; constructor(lengte, breedte, kleur, prijs){ this.lengte = lengte; this.breedte = breedte; this.kleur = kleur; this.prijs = prijs; Tafel.aantal++; console.log(`Tafel gemaakt, er zijn nu ${Tafel.aantal} tafel(s)`); } verkoop(){ console.log('Verkoop start...'); Tafel.aantal--; console.log(`Verkocht! Huidige voorraad van tafels is: ${Tafel.aantal}`); } verf(kleur) { this.kleur = kleur; console.log(`Tafel is nu ${this.kleur} geverfd`); } } let t1 = new Tafel(200, 90, "oud eiken bruin", 500); t1.verf("geel"); t1.verkoop(); let t2 = new Tafel(100,100, "meranti donker bruin", 1200); let t3 = new Tafel(150,70, "esdoorn met knoesten", 1500); t2.verkoop(); // HIER BEGINT DE 'BUREAU' KLASSE class Bureau extends Tafel { constructor(kleur, prijs, computerSteun){ super(kleur,prijs); this.computerSteun = computerSteun; console.log("Dit is een subklasse van Tafel, namelijk een bureau"); } } let b1 = new Bureau("grijs",200,true); if (b1.computerSteun){ console.log("Dit bureau heeft een computersteun!"); } console.log(`Aantal tafels is nu: ${Tafel.aantal} tafels`); b1.verkoop(); console.log(`Aantal tafels is nu: ${Tafel.aantal} tafels`); console.log(Bureau.aantal); Bureau.aantal = 8; console.log("Tafels: " + Tafel.aantal); console.log("Bureau's: " + Bureau.aantal); De bijbehorende Javascript code bij arrow functions / lambda expressies is de volgende: function Wijnfles() { this.aantalSlokken = 50; // Voorbeeld met een bestaande functie die twee parameters aan kan: setInterval(() => { this.aantalSlokken--; document.getElementsByTagName("progress")[0].value = this.aantalSlokken; }, 400); } var grandCru2005 = new Wijnfles(); En in de HTML staat dit: Voortgang:
En bij object.create() staat deze Javascript code: var Tafel = function() { var kleur = "bruin"; var hoogte = 100; } Tafel.prototype.verstelHoogte = function(){ this.hoogte++; } var Bureau = function(){ var computerVakje = true; } Bureau.prototype = Object.create(Tafel.prototype); // constructor van Tafel gebruiken var mijnBureau = new Bureau(); mijnBureau.hoogte = 90; console.log('Huidige hoogte is:' + mijnBureau.hoogte); mijnBureau.verstelHoogte(); console.log('Nieuwe hoogte is:' + mijnBureau.hoogte); HTML: Dit is de brontekst in een element
Dit is de het doel waar de bovenstaande tekst in gedropt mag worden
CSS: span, div { border: solid 1px black; } span { background-color: lightblue; } div { background-color: lightgray; } Javascript: window.onload = function() { bron = document.getElementsByTagName("span")[0]; doel = document.getElementsByTagName("div")[0]; bron.addEventListener("dragstart",function(e){ // Te kopieren data klaar zetten e.dataTransfer.setData("text/plain", bron.innerHTML); },false); doel.addEventListener("drop",function(e){ // Knippen: bron.innerHTML = ""; // Plakken: doel.innerHTML = e.dataTransfer.getData("Text"); },false); doel.addEventListener("dragover", function(e){ e.stopPropagation(); e.preventDefault(); }, false); doel.addEventListener("dragenter", function(e){ e.stopPropagation(); e.preventDefault(); }, false); } Zowel localStorage als sessionStorage maken gebruik van setItem() en getItem() methoden. Beide opslag mechanismen slaan gegevens op bij de eindgebruiker op de computer. JavaScript is immers een client-side taal. Concreet worden de gegevens bij localStorage zo opgeslagen dat ze bij later bezoek aan een webpagina, zelfs na afsluiten van de browser, nog te gebruiken zijn. SessionStorage behoudt de gegevens enkel gedurende het open staan van de window (of een tabblad zijn bij meerdere tabbladen). Zodra het tabblad of de browser in zijn geheel wordt afgesloten, gaan de gegevens verloren (tenzij ze, zoals in de praktijk, middels een server-side programmeertaal tijdig worden weggeschreven naar een database). Enkele veel toegepaste nieuwe HTML 5 API's zijn: File API WebSockets Drag & click bestaat niet, het is Drag and drop, onderdeel van de File API. Daarnaast is is er de localStorage (naast de sessionStorage) in plaats van de serverStorage - een onderdeel de WebStorage API.