On Github miroslavpopovic / i-hate-love-js
Prezentacija za HTML5/JavaScript korisnicku grupu, Banja Luka
Autor Miroslav Popovic / @miroslavpopovic
// DOM Level 0 (< IE5.5) var form = document.forms['formId']; // DOM Level 1+ var form = document.getElementById('formId');
// DOM - Web standard (IE9+ i svi ostali) var text = element.textContent; // IE, WebKit (Safari, Chrome), Opera var text = element.innerText;
// Prije DOM Level 2 element.onclick = function() { ... } // < IE9 element.attachEvent('onclick', function() { ... }); // DOM Level 2 element.addEventListener('click', function() { ... });Starije verzije IE i Opere vracaju element po imenu, ne po id-u innerText ne vraca sadrzaj style i script elemenata kao ni nevidljive elemente
if (navigator.userAgent.indexOf('MSIE') != -1) { // IE kod ovdje... } else { // Non-IE kod ovdje... }
<!--[if IE 6]> <html lass="ie6"> <![endif]--> <!--[if !IE]> <html lass="non-ie"> <![endif]-->Odredjivanje tipa i verzije browsera IE 10 je izbacio conditional comments
var modifyText = function() { ... }; if (element.addEventListener) { element.addEventListener('click', modifyText); } else { element.attachEvent('onclick', modifyText); }Polyfill - JavaScript shim - replicira ponasanje API-a prema web standardima Primjer - window.WebSockets
jQuery
var form = $('#formId'); var text = $(element).text(); $(element).click(function () { ... }); $(element).on('click', function () { ... });
Modernizr
Modernizr.load({ test: Modernizr.geolocation, yep : 'geo.js', nope: 'geo-polyfill.js' }); if (Modernizr.touch) { // ... } else { // ... }
alert('Ne radi ti ovo...');IE prije 10 godina Editori: Front Page, Dreamweaver
window objekat, global objekat
var glob = 'globalna varijabla'; function localScope() { var local = 'lokalna varijabla'; glob2 = 'globalna varijabla - nema var'; }
window.alert = function(message) { console.log(message); } alert('ovaj tekst ce biti ispisan u konzoli');
ne postoji block scope
if (condition) { var local = 'da li je ovo lokalna varijabla?'; } console.log(local);
var local; if (condition) { local = 'da li je ovo lokalna varijabla?'; } console.log(local);Hoisting
Automatic semicolon insertion
return { status: true };
return; // undefined { status: true };
// Ispravno koristenje return { status: true };
abstract boolean break byte case catch char class const continue debugger default delete do double else enum export extends false final finally float for function goto if implements import in instanceof int interface long native new null package private protected public return short static super switch synchronized this throw throws transient true try typeof var volatile void while with
var method; // OK var class; // greska object = {box: value}; // OK object = {case: value}; // greska object = {'case': value}; // OK object.box = value; // OK object.case = value; // greska object['case'] = value; // OKVecina rezervisanih rijeci se ne koristi unutar JavaScript jezika
typeof 55.4 // 'number' - OK var vrijednost = null; typeof vrijednost // 'object' !! // bolje rjesenje za null provjeru vrijednost === null // provjera da li varijabla sadrzi objekat if (vrijednost && typeof vrijednost === 'object') { // vrijednost je objekat ili niz (array) } // regularni izrazi typeof /a/ // 'object' ili 'function', zavisno od browseraPosto typeof ne moze da razlikuje izmedju null i object, moramo koristiti cinjenicu da je null falsy vrijednost, a da su objekti truthy;
var prvi = 100; var drugi = '50'; prvi + drugi // '10050' - konverzija u string
parseInt('20') // 20 parseInt('20 kg') // 20 parseInt('8') // 8 parseInt('08') // 0 !! - oktalni broj parseInt('08', 10) // 8 - radix parametar
0.1 + 0.2 === 0.3 // false, 0.1 + 0.2 = 0.30000000000000004 10 + 20 === 30 // trueSkaliranje brojeva sa pokretnim zarezom u integer rijesava problem... Npr. mnozenje sa 100
typeof NaN === 'number' // true 34 + NaN // NaN NaN === NaN // false NaN !== NaN // true isNaN(NaN) // true isNaN(0) // false isNaN('greska') // true isNaN('0') // false
0 // Number NaN // Number '' // String false // Boolean null // Object undefined // Undefined var value = myObject[name]; if (value == null) { console.log(name + ' not found.'); }
var value = myObject[name]; if (typeof value === 'undefined') { console.log(name + ' not found.'); }Falsy vrijednosti ne mogu da se zamjenjuju medjusobno; Prvi primjer je pogresan nacin za provjeru da li objekat sadrzi property.
var x = [1,2,3,]; //ERROR var y = {'a': 1, 'b': 2, 'c': 3,}; //ERRORProblem za IE < 9
'' == '0' // false 0 == '' // true 0 == '0' // true false == 'false' // false false == '0' // true false == undefined // false false == null // false null == undefined // true
Preporuka: Uvijek koristiti === i !==
== i != nisu tranzitivni Svi navedeni izrazi vracaju false sa ===with (obj) { a = b; } eval('a = a + 1'); setTimeout('...JS kod...', 1000); setInterval('...JS kod...', 1000); // ...with usporava JS procesor; eval takodje - pokrece kompajler - moguce izvrsiti bilo kakav JS kod; JSLint - By Douglas Crockford - za izbjegavanje ovakvih problema; JSHint;
var myObject = { 'prop1': 'value 1', 'prop2': 2, 'prop3': true, 'prop4': function() {} };
var myObject = { prop1: 'value 1', prop2: 2, 'class': 'info', prop4: function() {}, complex: { prop1: true, prop2: [ 1, 2, 10 ] } };
var arr = [ 1, 15, 54, 3, function() {}, 'test', { prop1: true} ];
// JSON - JavaScript object notation { isLoaded: true, message: 'ovo je JSON', items: [ { id: 1, name: 'item 1' }, { id: 2, name: 'item 2' }, { id: 3, name: 'item 3' } ] }new Object() i new Array() nisu preporucljivi; literali su jednostavniji za citanje i sigurniji (Object i Array je moguce redefinisati)
Ne samo sintaksa... vrijednost
// Mogu biti smjestene u varijablu, niz ili neki drugi objekat var myFunc = function() { }; var myFuncs = [ function() { /*...*/ }, function() { /*...*/ } ]; var myObject = { val1: true, val2: 10, func1: function() { /*...*/ }};
// Mogu biti argument neke druge funkcije var max = function(val1, val2) { return val1 > val2 ? val1 : val2; }, min = function(val1, val2) { return val1 < val2 ? val1 : val2; }; var find = function(items, compare) { var result = items[0]; for (var i = 1; i < items.length; i++) { result = compare(result, items[i]); } return result; }; var numbers = [5, 19, 44, 56, 2, 4]; var maxNumber = find(numbers, max); // 56 var minNumber = find(numbers, min); // 2
// Mogu biti povratna vrijednost neke druge funkcije var logFactory = function(type) { var consoleLog = function(message) { console.log(message); }, alertLog = function(message) { alert(message); }; return type == 'alert' ? alertLog : consoleLog; }; var log = logFactory('console'); log('Ovo ce biti ispisano u konzoli');
// Imaju sopstvene properties, posto su pravi objekti var myFunc = function() { /*...*/ }; myFunc.prop1 = 10; myFunc.prop2 = true; myFunc();
// Prototypal inheritance var Animal = function() { this.name = '-no name-'; }; Animal.prototype = { introduce: function() { console.log('Hi, I am ' + this.Name); } } var Cat = function() { /* ... */ }; Cat.prototype = new Animal(); var myCat = new Cat(); myCat.name = 'Kitty'; myCat.introduce();
var logFactory = function(type) { var logCount = 0, consoleLog = function(message) { logCount++; console.log('LOG ' + logCount + ': ' + message); }, alertLog = function(message) { logCount++; alert('LOG ' + logCount + ': ' + message); }; return type == 'alert' ? alertLog : consoleLog; }; var log = logFactory('console'); log('Ovo ce biti ispisano u konzoli sa rednim brojem');Ne postoji block scope, ali postoji function scope.
var numberRegex = /^-?\d+(?:\.\d*)?$/i; var isNumber = function(num) { return numberRegex.test(num); }; isNumber('10'); // true isNumber('number'); // false isNumber('-5.3'); // true isNumber('12.34.55.11'); // falsei flag u regularnom izrazu - ignore case
Pattern (sablon) je dokazano/testirano rjesenje odredjenog problema u razvoju softvera
Ponovno su iskoristivi su za slicne probleme
class Point extends Base { constructor(x,y) { super(); this[px] = x, this[py] = y; this.r = function() { return Math.sqrt(x*x + y*y); } } get x() { return this[px]; } get y() { return this[py]; } proto_r() { return Math.sqrt(this[px] * this[px] + this[py] * this[py]); } equals(p) { return this[px] === p[px] && this[py] === p[py]; } }
module math { export function sum(x, y) { return x + y; } export var pi = 3.141593; } import {sum, pi} from math; alert(sum(pi,pi));