Tekijät: Marko Haanranta, Kasper Kivikataja, Kati Kyllönen, Jussi Miestamo
Pääsivu
Tyyppiturvallisuuden tavoittelua 2. viikko
3. viikko
4. viikko
Javascriptissä muuttujat ja parametrit ovat tyypittömiä, mutta niiden arvoilla on tyypit. Javascriptin tietotyypit ovat merkkijono (string), luku (number), totuusarvo (boolean), taulukko (array), objekti (object), olematon (null) ja määrittelemätön (undefined). Vaikka muuttujilla ei olekaan tyyppiä, on arvojen tyyppejä syytä tarkistaa, jotta ohjelmat eivät tuottaisi odottamattomia tuloksia. Erityisesti käyttäjän syötteitä on hyvä tarkastella virheiden varalta. Javascriptissä yhteenlasku voidaan suorittaa ongelmitta luvun ja String-tyypin olion välillä.
function sum(a,b){
return (a+b)
}
write(sum(2,"w4")) //tulostaa "2w4"
Javascript tarjoaa - kuten tunnettua - funktiot parseInt()
ja parseFloat()
kokonais- tai liukulukujen eristämiseen syötteestä: jos syöte alkaa numerolla, siitä erotetaan numero-osa, ja loppu jätetään huomiotta. Joissain tapauksessa tämä on täysin riittävä tapa varmistaa se, että syöte on kelvollista. Jos ohjelmoija odottaa saavansa syötteenä esimerkiksi kokonaisluvun, vaaraa ei ole, koska parseInt()
palauttaa aina kokonaisluvun tai tietotyypin undefined
. Tietysti ohjelmakoodin pitää olla rakennettu niin, että undefined
:iin on varauduttu, mutta käytettiin mitä tahansa keinoa tyyppien tarkastamiseen, undefined
:iin on joka tapauksessa aina varauduttava, jotta ohjelman toiminta olisi ennakoitavaa.
Vaikka yllä oleva esimerkki on yksinkertainen, pelkkä undefined
:iin varautuminen ei riitä. Koska oletettavaa on, että käyttäjä (tai funktiota kutsuva ohjelmoija) ei kirjoita syötteeseen lainausmerkkejä, esimerkin syötteen tekee kelvottomaksi todennäköisemmin käyttäjän lyöntivirhe:
write(sum(2,w4)) //Tulostaa konsoliin ReferenceError: w4 is not defined;
Tällaisten tilanteiden varalta pitäisikin tarkistaa, onko syöte ylipäätään kokonaisluku. On onnekasta, jos syöte alkaa numeroilla, mutta jos ei ala, parseInt()
ei pelasta.
Tyyppien tarkistus ohjelmakoodissa on erityisen tärkeää juuri käyttäjän syötettä käsiteltäessä, sekä muutoinkin ohjelman ulkoisissa rajapinnoissa.
Tarkastusfunktio onko muuttujan arvo undefined
function isUndefined (value) {
return typeof value === 'undefined'
}
Tarkastusfunktio onko muuttujassa arvo
function hasValue(value) {
if(value){
return true
}
return false
}
Tarkastusfunktio numerolle
function isNumber(value) {
return typeof value === 'number'
}
Tarkastusfunktio kokonaisluvulle (jos value = 1.0, eli kun desimaaliosa on nolla, niin tulkitaan kokonaisluvuksi)
function isInteger(value) {
return value === Math.floor(value)
}
Tarkastusfunktio desimaaliluvulle (jos desimaaliosa on nolla, niin ei tulkita desimaaliluvuksi)
function isDouble (value) {
return typeof value === "number" && !isNaN(value) && value !== Math.floor(n)
}
Tarkastusfunktio merkkijonolle (tässä tyhjä merkkijono tulkitaan merkkijonoksi)
function isString(value) {
return typeof value === 'string'
}
Tarkastusfunktio funktiolle
function isFunction(func) {
var getType = {};
return func && getType.toString.call(func) === '[object Function]';
}
Tarkastusfunktio objektille
function isObject(object) {
return typeof object === 'object';
}
Tarkastusfunktio taulukolle
function isArray(value) {
return value instanceof Array;
}
Tarkastusfunktio booleanille
function isBoolean(value) {
return typeof value === 'boolean';
}
Köyhän miehen esimerkki tyyppiturvallisuutta tavoittelevasta ohjelmointityylistä, viikon 1 kuusitehtävää mukaillen.
var korkeus = parseInt(prompt("Anna kolmion korkeus:"));
if (hasValue(korkeus) && isNumber(korkeus)
&& korkeus > 0 && korkeus < 22){
var alimman_leveys = 1 + ((korkeus-1)*2);
var taman_leveys = 1;
var tyhjia = (alimman_leveys-taman_leveys)/2;
for (var i = 0 ; i < korkeus; i++){
var tyhjat = new Array(tyhjia+1).join(" ");
var tahdet = new Array(taman_leveys+1).join("*");
write(tyhjat + tahdet);
taman_leveys = taman_leveys +2;
tyhjia = (alimman_leveys-taman_leveys)/2;
}
}
else{
alert("Ei käy");
}
Voidaan tietysti pohtia, kuuluuko dynaamisesti tyypitettyjen kielten luonteeseen lainkaan tyyppiturvallisuuden tavoittelu. Kuitenkin, jos tavoitellaan ennustettavasti toimivaa ohjelmaa on se mielestämme tarpeen. Tarjolla on kuitenkin useita keinoja varmistaa käyttäjältä tulevan syötteen oikeellisuus käyttämällä esimerkiksi javascript-ohjelmointikehysten tarjoamia lomakevalidaattoreita. Säännölliset lausekkeet ovat myös yleisesti käytetty, varsin tehokas tapa käyttäjän syötteiden tarkastamiseen.
Tätä tehtävää tehdessämme, löysimme kyseisen artikkelin MikroPC-lehdestä
Olli Vänskä, MikroPC, 5.8.2013, 9:25 Työntekijän nimi "Nolla" sotkee yrityksen koko henkilöhaun Mikään tietojärjestelmä ei ole täydellinen, mutta joskus ongelmia esiintyy varsin kummallisista syistä. Erään yrityksen työntekijähaku kaatui jatkuvasti sen takia, että sen palkkalistoilla on mies nimeltä Null (Nolla).
http://www.mpc.fi/kaikki_uutiset/article918607.ece
Lähteet:
http://www.w3schools.com/js/js_datatypes.asp
http://www.cs.helsinki.fi/u/wikla/OTjs/materiaalia/tyyppeja/
http://united-coders.com/matthias-reuter/handling-the-unexpected-type-safe-functions-in-javascript/