JavaScript

Käsitellään JavaScript-ohjelmointikielen perusteet. Javascript on ohjelmointikieli jota käytetään erityisesti WWW-sivujen yhteydessä.

Luennolla tehty esimerkki: malli.html ja malli.js

ECMAscript

Javascript on alunperin kehitetty Netscape-selaimeen 1990-luvulla. Javascript-kieli on nykyään standardoitu ECMAScript-standardissa. ECMAScript-kieltä kehitetään edelleen. Tällä hetkellä uusin versio on ECMAScript 2018 mutta käytännössä käytössä on ECMAScript 2015 (ES6).

Voit kirjoittaa Javascriptia uusimmalla kielen versiolla ja kääntää Babelin avulla vanhempaan versioon.

Javascript (ECMAScript) -kieltä käytetään useissa eri yhteyksissä, mutta erityisesti WWW-selaimissa. Selaimessa suoritetulla Javascriptilla voi muokata selainympäristöä ja siihen liittyviä objekteja.

JavaScript-ohjelman suorittaminen

Javascript-ohjelmat suoritetaan yleensä selainympäristössä. Tämä tarkoittaa javascript-sovelluksen linkittämistä WWW-sivun yhteyteen. Javascript-ohjelma pääsee käsiksi kyseisen WWW-sivun sisältöön ja sen ulkoasuun.

Javascript liitetään www-sivuun script-elementillä yleensä head-osassa:

<script type="text/javascript" src="jokutiedosto.js"></script>

Mallipohja:

<!DOCTYPE html>
<html lang="fi">
<head>
<meta charset="UTF-8" />
<title>Mallipohja</title>
<script type="text/javascript" src="malli.js"></script>
</head>
<body>
</body>
</html>

Javascriptia voi harjoitella myös suoraan selaimessa konsolin tai scratchpadin avulla tai JSFiddle- ja jsbin-palveluissa.

Työvälineet

Syntaksi

Javascriptin syntaksista kannattaa lukea seuraavia lähteitä:

Suositeltavaa on suorittaa ohjelma Strict modessa. Kirjoita ohjelmakoodisi alkuun rivi:

"use strict";

Ympäristö

JavaScriptiä suoritetaan määrätyssä ympäristössä, joka voi olla esimerkiksi selaimessa. JavaScript ei itsessään määrittele, miten tietoa voidaan syöttää tai tulostaa, vaan se tarjoaa ainoastaan tiedon käsittelymekanismit. Tiedon syöttö ja vasteiden anto tehdään käyttäen HTML:ää ja Document Object Model (DOM) -rajapintaa.

Yleistä

Muuttujat

JavaScript on heikosti tyypitetty kieli. Muuttujien tyyppi määräytyy siis arvon perusteella.

Voit halutessasi käyttää TypeScript-kieltä, joka lisää javascriptiin vahvan tyypityksen. TypeScript-koodi käännetään tavalliseksi Javascriptiksi.

Tietotyypit

Javascript muuntaa automaattisesti muuttujan tyyppiä tilanteen mukaan.

Muuttujat esitellään seuraavasti:

var x = 1.0;
var s = "Diiba daaba";

totuus = true; // globaali muuttuja, näkyy kaikissa funktioissa. Ei toimi Strict-moodissa. Älä käytä.

// lohkon sisäinen muuttuja
let foo = "daaba dii";

// vakio, ei voida muuttaa
const foobar = "vakio";

var bar; // määrittelemätön arvo, undefined

if ( bar === undefined ) {
   console.log("bar on undefined");
}

if (bar) {
 // jos bar on tosi
}
else {
  // tämä toteutuu, koska undefined on sama kuin false
}

var luku = bar + 1; // luku saa arvoksi NaN 

Muuttujien nimeämissäännöt ovat kuten Javassa.

Jos muutat String-tyyppiä Number-tyypiksi niin tee se parseInt- tai parseFloat-funktiolla.

kts. myös isInteger

Huomioi seuraavaa:

Lohkot

Muuttujan näkyvyys rajoittuu funktion sisälle, jos muuttuja esitellään var-etuliitteellä. Ennen ECMAScript 2015:sta ja let-muuttujanesittelyä Javascriptissa EI ole ollut lohkon sisäisiä muuttujia

function foobar() {
  var p = 1; // tämä muuttuja on voimassa vain tässä funktiossa
  {
    var p = 2; // Tällä on sama näkyvyysalue kuin edellisellä
  }
  console.log(p); // tulostaa 2
  
}

Operaattorit

Käytössä on normaalit aritmeettiset ja vertailuoperaattorit. Vrt. Java

delete-operaattori poistaa objektin, ominaisuuden tai elementin taulukosta.

typeof-operaattori palauttaa merkkijonon, joka kertoo kohteena olleen objektin tyypin.

in-operaattori palauttaa true jos kysytty ominaisuus löytyy kohteena olevasta objektista.

instanceof-operaattorilla voi testata objektin tyypin

new-operaattorilla voi luoda uusia objekteja

Merkkijonot

Merkkijonot ovat olioita, joilla mm. seuraavia metodeja:

Merkkijonoja voi operoida seuraavilla operaattoreilla:

+
Liittää merkkijonot yhteen
< > <= >= ==
Vertailee aakkosjärjestystä
s[n]
Antaa merkkijonon s n:nnen kirjaimen

Merkkijonoja voi siis käsitellä kuin taulukoita eli merkkijono.charAt(0) on sama kuin merkkijono[0]

merkkijonoja voidaan javascriptissa yhdistellä yksinkertaisesti +-operaattorilla

let foo = "tämä" + "tämä"
Myös taulukosta voi helposti tehdä merkkijonon ja käyttää haluttua erotinmerkkiä
let foo = ["teksti1","teksti2", "teksti3"]
console.log( foo.join(";") );
 

Merkkijonojen tyyppien muunnoksiin on olemassa muutama globaali funktio:


var luku = parseInt("567");
var luku = parseInt("567", 10); // toinen argumentti kertoo kantaluvun. Tässä kymmenjärjestelmä
var luku = parseInt("0567"); // ei toimi kuten voisi kuvitella. etunolla tarkoittaa, että luku saatetaan käsitellä oktaalijärjestelmässä.
var luku = parseInt("0567", 10); // tämä toimii
var luku = parseInt("101", 2); // binääriluku

Ehtolauseet

if...else:

if (ehto) {
   jos oli tosi...
}
else {
   jos oli epätosi...
}

switch

switch (expression) {
  case label_1:
    statements_1
//    break;
  case label_2:
    statements_2
//    break;
//    ...
  default:
    statements_def
}

Silmukat

for- ja while-silmukat toimivat kuten Javassa.

Labelilla voi nimetä tietyn loopin jolloin voi break- tai continue-komennolla viitata tähän looppiin.

ulompi:
    while(true) {
        console.log('ulompi silmukka');
        let x = 0;  
        while(true) {
          console.log('sisempi...');
          x = x + 1;
          if ( x > 10) {
            break ulompi;
         }
        }
   }

for..in ja for..of toimivat hieman eri tavoilla.

var taul = [3, 5, 7];
taul.foo = 'kukkuu';

for (var i in taul) {
   console.log(i); //  "0", "1", "2", "foo"
}

for (var i of taul) {
   console.log(i); //  3, 5, 7
}

for..in käy läpi taulukon alkioiden numerot ja myös itse määriteltyjen attribuuttien nimet. for..of käy läpi oikeat taulukon arvot

Poikkeukset

try {
   kokeillaan jotain ...
   // throw 'no ny sekos';
}
catch (e) {
  tuli poikkeus...
  console.log(e);
}

Error types

Promise

Käytetään asynkronisten funktioiden yhteydessä.

Using promises

Taulukot

Taulukko luodaan Array-oliolla

var paikat = new Array();
paikat[0] = "Jämsä";
paikat[1] = "Äänekoski";

tai hakasulkeilla:

var paikat = ["Jämsä", "Äänekoski"];

Taulukkoon lisääminen onnistuu seuraavasti:

paikat[paikat.length] = "Jyväskylä";
paikat.push("Jyväskylä");

Taulukko on kuten Object, mutta taulukolle on määritelty length

Taulukot ovat oikeasti osoittimia. Taulukkoa ei voi kopioida pelkällä sijoitusoperaatiolla. kts. Array.from ja slice, jotka tekevät shallow-kopion taulukosta. Jos haluaa oikean kopion niin kopiointi on ohjelmoitava itse.

Delete vs. splice

Javascript-taulukosta poistaminen tapahtuu splice-metodilla.

On olemassa myös delete-operaattori, joka poistaa ominaisuuksia objekteilta. Taulukon alkioiden yhteydessä tämä tarkoittaa käytännössä taulukon alkion muuttamista undefined-tyypiksi. Taulukon koko tai indeksointi ei muutu, jos käyttää delete-operaattoria. Delete on tarkoitettu objektien ominaisuuksien poistamiseen eikä taulukon alkioiden poistamiseen.

Taulukon alkiot voi helposti yhdistää join()-metodilla.

Set

Set on taulukko johon voi tallentaa vain uniikkeja arvoja.

Map

Map on tietorakenne johon voidaan tallentaa avain-arvo-pareja. Vrt. Python dict

Funktiot

Funktion voi esitellä seuraavasti:

function summaa(x,y) {
  return (x + y);
}

summaa = function(x,y) {
  return (x + y);
}

function foobar(x,y) {
  // tämä funktio toimii vain funktion foobar-sisällä
  var p = 1;
  function barfoo(x) {
    // ulomman funktion muuttujat ovat käytettävissä
    return x*p;
  }

}

// parametreille voidaan antaa oletusarvot
function f(x=0,y=1) {
  return x+y;
}

Huomioitavaa:

Javascriptin funktiokutsuissa on oletuksena käytössä pass by value, paitsi jos parametreina on objekteja tai taulukoita jolloin toimii pass by reference.

Objektit

Assosiatiivisia "taulukoita" (nimi-arvo-pareja) voi tehdä seuraavasti (vrt. Map):

Objektit ovat oikeasti osoittimia. Objektia ei voi kopioida pelkällä sijoitusoperaatiolla. Kts. Object.assign(), joka tekee objektista shallow-kopion.

var lampo = new Object;
lampo["jkl"] = -6;
var saatilat = {
  jämsä: "Aurinkoinen",
  äänekoski: "Pilvipoutaa"
};

for (var i in saatilat) {
	console.log( i + " : " + saatilat[i] );
}

Assosiatiivinen "taulukko" on itseasiassa objekti, jolla on attribuutteja. Tämä voi aiheuttaa jossain tilanteissa hämmennystä. Vrt. Map

JavaScript (joka pohjautuu Ecmascript 3 -standardiin) on prototyyppi-pohjainen kieli ja siinä ei ole luokkia samassa mielessä kuin Java/C++/C#-kielissä vaan pelkästään olioita (objekteja). JavaScriptissä omia olioita voidaan luoda seuraavasti:

// konstruktori-funktio
function Koordinaatti(x,y) {
  this.x = x;
  this.y = y;
}

// Koordinaatin "public-metodi"
Koordinaatti.prototype.normi = function() {
  return Math.sqrt(Math.pow(this.x, 2) + Math.pow(this.y, 2));
}

var piste = new Koordinaatti(1,2);
piste.normi();

Voidaan käyttää myös modernimpaa class-syntaksia:

class Polygon {
  constructor(height, width) {
    this.name = 'Polygon';
    this.height = height;
    this.width = width;
  }
}
class Square extends Polygon {
  constructor(length) {
    // super kutsuu Polygonin konstruktoria. Suoritettava ennen kuin voi käyttää this
    super(length, length);
    this.name = 'Square';
  }
}
var poly = new Polygon(10, 10);
var nelio = new Square(20);

Objekteja laajennetaan toisten objektien avulla käyttäen prototype-määritystä. Private-attribuutteja ja -metodeja on mahdollista luoda pienellä vaivalla.

// muistakaa, että attribuutteja (avaimia) voi vapaasti keksiä
let testi = new Object();
undefined
testi.foo;
undefined
testi.foo==undefined
true
testi.foo = "koe";
"koe"
testi.foo==undefined;
false
delete testi.foo;
true
testi.foo==undefined;
true
// muistakaa, että objekteilla testi.bar on sama asia kuin testi["bar"]
testi["bar"] = "koe2";
"koe2"
testi.bar;
"koe2"
testi.bar==undefined;
false
delete testi["bar"];
true
testi.bar==undefined;
true

Tarpeellisia funktioita

Array.sort()

Javascriptin taulukoita järjestettäessä täytyy itse kirjoittaa oma vertailufunktio (compareFunction), jos taulukoissa on esim. objekteja tai muuta monimutkaisempaa sisältöä. Jos on huolimaton tämän funktion kanssa niin ampuu helposti itseään jalkaan. Väärin kirjoitettu funktio voi tuurilla toimia firefoxissa, mutta ei toimikaan esim. Chromessa.

Jos vertaillaan numeroita niin vertailufunktion voi kirjoittaa lyhyesti näin:

function compareNumbers(a, b) {
   return a - b;
}

Jos a ja b ovatkin stringeja niin ylläoleva funktio ei toimikkaan oikein.

Jos vertaillaan lähes mitä tahansa muuta kuin numeroita niin funktion ON oltava seuraavaa muotoa:

function compare(a, b) {
   if (a is less than b by some ordering criterion) {
     return -1;
   }
   if (a is greater than b by the ordering criterion) {
     return 1;
   }
   // a must be equal to b
   return 0;
}

Suositeltavaa on käyttää aina tätä jälkimmäistä niin ei vahingossa satu omaan jalkaan.

Date

Päivämäärä

var aika = new Date();
alert(aika.getDate() + "." + aika.getMonth() + "." + aika.getYear());

Kulunut aika

var aika = new Date();
var hetkiA_msec = aika.getTime();
// tehdään jotain
var hetkiB_msec = aika.getTime();
var kulunutaika = new Date(hetkiB_msec - hetkiA_msec);
alert(kulunutaika.getSeconds());

Math

Satunnaisluvut

var sanoja = ["Diiba","Daaba","Tesmaus","Heppa","Muuli","Saippuakauppias","Jepjep"];
// pyöristys alaspäin( 0-0.999999999 * 7 )
var rand = Math.floor( Math.random() * sanoja.length );
console.log(sanoja[rand]);

Pyöristäminen ja numeroiden muotoilu

var liukuluku = 3.245200004;
var kaksidesimaalia = Math.round(liukuluku*100)/100

Numeroiden mutoilu on helpointa tehdä Intl.NumberFormat-avulla.

isNaN

Tutkii onko muuttuja erikoisarvoa NaN (not a number). NaN-arvoa ei voi vertailla muulla kuin tällä funktiolla.

var numero = parseInt(document.getElementById("tekstikentta").value);
if (isNaN(numero))
  document.getElementById("tekstikentta").className = "red";

typeof

Operaattorit: typeof - Core JavaScript 1.5 Reference

Palauttaa stringinä muuttujan tyypin.

Käyttäjien kommentit

Kommentoi Lisää kommentti
Kurssimateriaalien käyttäminen kaupallisiin tarkoituksiin tai opetusmateriaalina ilman lupaa on ehdottomasti kielletty!
http://appro.mit.jyu.fi/tiea2120/luennot/javascript_basics/
© Tommi Lahtonen (tommi.j.lahtonen@jyu.fi) <http://hazor.iki.fi/>
2018-12-14 14:16:38
Informaatioteknologia - Jyväskylän yliopiston informaatioteknologian tiedekunta