advanced javascript – a journey from alert to high order functions – basics



advanced javascript – a journey from alert to high order functions – basics

0 0


js_tutor

MO JS tutorial

On Github defectus / js_tutor

advanced javascript

a journey from alert to high order functions

Created by Ondrej Linek/ @defectus

what's covered

  • basics
  • types
  • operators
  • objects
  • scopes
  • events
  • jquery

basics

  • JavaScript is an interpreted object oriented/functional language
  • invented in 1996 as LiveScript
  • implementation of JavaScript runs in browsers and command line

basics-implementation

  • JavaScript is interpreted
  • JavaScript is dynamic
  • JavaScript is single threaded
  • JavaScript is event driven

basics-functions

  • 3 ways to define/declare a function
  •                                     function a(){} // anonymously function(){}
                                    
  •                                     var a = function a(){}
                                    
  •                                     var a = new Function a('')
                                    
  • functions can take functions as parameters and can return functions
  • all parameters are optional
here we should try to define a function and ty to call it with no argument, more than declared arguments and less than defined arguments. Use arguments to access the parameters. We can also demo anonymous function and its execution.

basics-functions

  • 3 ways to execute a function
  •                                     a(param1,param2,param3...)
                                    
  •                                     a.call(this, param1, param2, param3)
                                    
  •                                     a.apply(this, [params])
                                    
here we should try to call a function within a scope of a different object

basics-miscs

  • semicolons are optional as long as intepreter can fix errors by adding them at the line end
  • $ and _ are valid identifiers i.e. function $(){} or var _ = 1 is allowed
here we should try to call a function within a scope of a different object

types-overviews

  • javascript is weakly typed but supports types
  • use typeofto determine variable type
  • basic types include numbers, strings, dates, logical values
  • you can create and use arrays and custom objects
here we could define an array and object and get its type using typeof

types-arrays

  • to define an array you can use
  •                                     var a = new Array();
                                    
  •                                     var a = [];
                                    
  • to add to an array a.push(0)
  • to remove from an array a.pop()
here we could define an array and object and get its type using typeof

types-objects

  • to define an object you can use
  •                                     var o = new Object();
                                    
  •                                     var o = {};
                                    
  • to add to an object o.prop=val
  • to add to an object o['prop']=val
  • to remove from an object o.delete('prop')
here we could define an array and object and get its type using typeof

types-built-in

  • other built-in object (constructors) we can use
  • String for textual data
  • Number for numeric data
  • Date for dates
  • Function for on the fly functions
  • RegExp for regular expressions
we may want try to create instances of these objects

types-the rest

  •                                     1/0 === Infinity
                                    
  •                                     -1/0 === -Infinity
                                    
  •                                     NaN !== NaN
                                    
  • String for textual data
  • Number for numeric data
  • Date for dates
  • Function for on the fly functions
  • RegExp for regular expressions
we may want try to create instances of these objects

operators

  • this sections covers operators that differ from java only
  • &&, ||, === and !==
  • new, delete and in
  • instanceof and typeof
  • ., [] and ()

operators-logical

  • apart from well know java unary and binary operators
  • && returns first operator if it can be converted to false
  • || returns first operator if it can be converted to true
  • === returns true if value and type are the same
  • !== returns true if value and type are not equal
demo difference between == and ===

operators-objects

  • to create an object use newoperator new Constructor( param1,param2,param3...)
  • to check if an object has a property use in 'length' in 'hello world'
  • use delete to delete an object or its property (can't be used to delete var)

operators-objects, continued

  • typeof returns string containing the type of the operand
  • e.g. typeof 'hello' === "string"
  • use instanceof to determine whether an object's prototype is contained in prototype chain of the provided Constructor
  •                                     ('string' instance String) === true
                                    
  • note that custom object by default inherit from Object unless you change their prototype
show {} instanceof Object, new String instanceof object and String ...

operators-the rest

  • . and [] are used to access properties (in case of arrays [] accesses items in them)
  • e.g. object['prop'] is equal to object.prop
  • () calls a function
we could demo here accessing props and items in array

objects

  • javascript's concepts of objects differ from java
  • objects don't have classes but prototypes
  • to create an object you have to call a constructor using the operator new
  • object's properties can be accessed via . or []
here we can create a new object like function constr(aa) {this.prop1 = aa}; var a = new constr('obj1'); var b = new constr('obj2'); console.log(a.prop1); console.log(b.prop1); console.log(a.prop2); constr.prototype.prop2 = 'added later'; console.log(a.prop2); console.log(b.prop2); a.prop2 = 'modified later'; console.log(a.prop2); console.log(b.prop2);

objects - creating new

  • to create a new object
                                var obj = {} // prototype will Object
                            
                                var obj = function(){} // prototype will be Function
                            
                                var obj = new function(){} // prototype will be Object
                            
explain how to create one of "maps" and how to create constructors

objects - adding properties

  • using constructor e.g. function Constructor (a, b, c) {this.a = a; this.b = b; this.c = c}
  • using "." or [] e.g. var a = {}; a.prop1 = 'val1'; a[prop2] = 'val2'
  • using prototype var a = {}; a.prototype.prop1 = 'val1'
  • functions are values in JS hence: var a = {}; a.fun1 = function (){return 'val1'}; a.fun1
explain how to create one of "maps" and how to create constructors

objects - enumerating

  • for - in loop
                                        for (var propName in object) {console.log(propName + '=' + object[propName])}
                                    
  • Object.keys()
                                        var a = {b:'b'}; Object.keys(a);
                                    
  • Object.getOwnPropertyNames()

objects - inheritance

  •                                     function Constr1(val1){ this.prop1=val1; this.print=function(){alert(this.prop1)}
                                            } function Constr2(val1,val2){ Constr1.call(this, val1); this.prop2=val2;
                                            this.print2=function(){alert(this.prop1 + '-' + this.prop2)} } Constr2.prototype=Object.create(Constr1.prototype);
                                            var obj = new Constr2('a', 'b'); obj.print(); obj.print2();
                                    

scopes

how to define how to access self-calling code

scopes

  • JavaScript code runs in scopes
  • variables are by default defined in global scope (if you ommit "var" then it is always global scope)
  • if no scope is define, javascript uses main scope called "global"
  •                                     window === global // true
                                    
  •                                     window.alert = function(){window.confirm('we\'ve got a problem!')};alert('hello
                                            world');
                                    
  • global scope can get cluttered quickly, we better define our own scopes

scopes-definition

  •                                     var scope = {var1:'val1'}; alert(scope.var1);
                                    
  • safer to do so is to use jQuery.extend
  •                                     var scope = jQuery.extend({}, {var1:'val1'}); alert(scope.var1);
                                    

scopes-accessing

  • scopes can be nested
  • properties deeper in scopes can access properties higher, but not other way round
  • properties deeper in scopes can overload properties higher

scopes-self calling code

  • scopes can be nested
  •                                     function a () {alert('a called')} a = (function(a){ return function(){
                                            alert('about to call a'); a();}})(a); a();
                                    

events

  • events are the heart of javascript
  • we'll focus on DOM events, event-loop machines such as node.js can be discussed later
  • listening for events
  • creating events

events - listening for

  • in IE element (or simply event emitter)
                                        element.attachEvent('event', handler);
                                    
  • in newer browsers
                                        element.addEventListener('event', handler);
                                    

events - triggering

  • to trigger an event use
                                        element.dispatchEvent(event);
                                    
  •                                     var event = document.createEvent('MouseEvent'); event.initMouseEvent(.....);
                                            element.dispatchEvent(event);
                                    
  • in IE you can use
                                        element.event(); e.g. element.click();
                                    

jQuery

  • first release in 2006
  • library that aims to standardize javascript access to DOM (abstraction layer)
  • adds many extra functions helping with common tasks (AJAX, animation, effects and more)
  • allows users to extend its functionality by adding plugins and new features
jsfiddle link

jQuery

  • what is the difference between == and ===
  • == compares on equality === compares on identicality
  • do javascript objects have classes?
  • no
  • when would you use apply and call?
  • to call a function
  • do we have to use semicolons to indicate statement ends
  • not always
  • what's easiest way to create an object?
  • {}
  • in browser, what's the other name of the global scope?
  • window

mighty $

  • $ is in javascript a valid function name
  • $ function returns collection of jQuery objects
  • $ as an object contains many useful functions (like each, map)
  • if you don't want to/can't use $ you can fallback to jQuery" - $("p") == jQuery("p")

$ use cases

  • $ can be used as an element selector: $("p") selects all P elements in the current document
  • $ can be used as a wrapper: $(document) returns jQuery wrapped document object
  • $ can be used to create elements: $('<p>') returns a new P element
  • $ can be used to access utility functions: $.ajax({ url: "/url",data: { key: "val" }}) calls /url?key=val

selectors and further

  • tag - selects elements by tag name
  • .class - selects elements having class
  • #id - selects elements of the id
  • [attr=value][attr2=value2]- selects elements where an attribute attr equals value and attribute attr2 equals value2

more fun with selectors

  • tag.class tag with a class
  • tag#id.class tag with a class and id
  • tag#id.class1\\.class2.class3 tag with 2 classes (class1.class2 and class3) and id
  • tag1 tag2 tags that have a (direct or indirect) parent tag2
  • tag1>tagt2 tags that have a direct parent tag2

even more fun with selectors

  • tag1, tag2 selects elements of tag1 and tag2
  • tag1 + tag2 selects tags2 that are immediatelly precedet by tags2
  • tag1 ~ tag2 selects all siblings of tag2 following tag1
  • tag:even, tag:first, tag:last selects all even tags + first and last

events

  • .on(events, elements, data, handler) - attaches a handler to listen for events
  • $("div").on("click", handler) - attaches handler to listen for click events all divs.
  • $("div").on("click dblclick", 'p.clickable', {data:'data'}, handler) - attaches handler to listen for click events on all p.clickable (now and in future) within all divs.

event handlers

  • false - if you to cancel that event straight away
  • a function that takes one parameter - the event - var handler = function (e) {...}
  • event.preventDefault() - if you don't want the event to actioned on
  • event.stopPropagation() - event will not bubble up
  • event.target - element triggering the event
  • event.data - arbitrary data provided during on() call

chaining

  • jQuery allows code o be chained
                                $("div").css({color:'blue'}).on('click', handleClick).append(whatever);
                            
that's because many (not all!) functions return jquery object allowing calling additional functions use it whenever possible - the most epxensive operation is to actually find something

ajax - take 1

  • load() - replaces body of element(s) with data loaded from a url
                            
$("p.replaceMe").load( "ajax/replace.html"); 
$("p.replaceMeOnlyPart").load("ajax/replace.html#replaceBit"); 
$("p.replaceMeWith").load("ajax/replaceWithParams",{what:'anything'}); // POST method used! 
$("p.replaceMe".load("ajax/replace", function(){alert('replaced')}));
                        

ajax - take 2

  • $.get() - loads content
                            
$.get("callMe") // ping - requests data but ignores result 
$.get("getMe", function(data){alert("received:" + data)}) // calls and gets result 
$.get("getMeWithParams",{param1:"val1"}, function(data){alert("received:" + data)})  // calls with paramters and gets result
                        

ajax - take 3

  • $.ajax() - performs ajax calls
                            
$.ajax(
    {url:"ajax", 
    success:function(data){alert("recevived:" + data)}},
    error:function(data){"error:" + data.statusText});
$.ajax({url:"ajax", 
    type:"POST", 
    success:function(data){alert("recevived:" + data)}}, 
    error:function(data){"error:"+ data.statusText}) // use POST method 
$.ajax({url:"ajax", 
    type: "POST",
    data: {param1:"value1"}, 
    success:function(data){alert("recevived:" + data)}},
    error:function(data){"error:" + data.statusText}) // use POST with params
                        

promises

  • a functional way of dealing with asynchronous programing
  • a promise is a value that will be fulfilled later however can still be passed around
                                
$.get("ajax").done(function(data) { alert("done:" + data)}) 
// when this ajax resolves call this function
                            

more promises when -> then

  • when allows to define a master promise based on combined promises
                                    
$.when($.ajax("getData1"), $.ajax("getData2"))
.then(function(data1, data2) {alert("done:" + data1 + data2)},
    function(fail1, fail2){alert("failure:" + fail1 + fail2)}) // when all ajax resolve call this function
                                
in case of single parameter the parameter is encapsulated as deffered
                                    
$.when($.ajax("getData1"))
.then(function(data1) { alert("done:" + data1)},
    function(fail1){alert("failure:" + fail1)}) // when this ajax resolves call this function
                                

creating promises

  • to centralize callbacks and allow passing them around a values we can create promises ourselves
                                    
var defo = $.Deferred(); 
defo.done (function(data){alert("done1:" + data)})
.done(function(data){alert("done2:" + data)}) 
$("body").on("click", function(){defo.resolve("val")})
                                
if you want to prevent others from messing with your deffered objects then return the underlying promise e.g. defo.promise()which disallows resolving, notifying etc.

animations

  • the simplest $("p").toggle()shows/hide element(s) in 400ms
  • simultaneously $("p").show({queue:false}).slideDown({queue:false})both animations will run the same time
  • to stop running animations $("p").stop().slideUp()
  • to chain $("p").slideUp(function(){$(this).slideDown()}})

utility functions

  • $.each() - iterates over an array or object $.each({key:"value", function( k, v ) {alert("Key: " + k + ", Value: " + v )})
  • $.data() - stores/reads data at element level $.data(document.body, "data", "value"); alert($.data(document.body, "data"))
  • $.map() - applies a function on all array items and return results as a new array $.map(['a','b','c'], function(a,i){return a.toUpperCase() + i})
  • $.parseJSON() - converts JSON string into JS object $.parseJSON('{ "key": "val" }')
  • $.extend() - merges a target object so it contains all fields of the source object $.extend({a:'a',b:'b'}, {b:'bb',c:'cc'}) // returns {a:'a',b:'bb',c:'cc'}

extending jQuery

a quick example of a plugin below

(function($) { // closure
    // Plugin starts here
    $.fn.hilight = function( options ) {
        var $this = this;
        debug(this);
        return this.each(function() {
            var markup = $this.html();
            markup = "" + markup + ""
            $this.html( markup );                                
            });
    };
    // Private function for debugging.
    function debug( $obj ) {
        if ( window.console && window.console.log ) {
            window.console.log( "selection count: " + $obj.size() );
        }
    };
})(jQuery); // we call the closure straight away
                            

optimizing jQuery

  • use fast selectors followed by slow - $("#id").find("[attr='val']")
  • chain functions $("input.class:selected").addClass("newclass").hide()
  • cache elements var $inputs = $("input.class:selected"); $inputs.addClass("newclass")
  • use vanilla.js!

vanilla.js

  • it's not shame to use vanilla javascript - many times it's much faster than JQuery
  • to get an element you can still do document.getElementById("id")
  • to get based on a css class document.getElementsByClass("class")
  • to get based on a css style selector document.querySelectorAll("p.class")
  • any element can be converted into an JQuery object by $ - $(document.getElementById("id"))
  • you get elements back from JQuery by $("p").get(0)

vanilla js animate

to animate an element vanilla js style:
                            
var s = document.getElementById('toFade').style; 
s.opacity = 1; 
(function fade(){(s.opacity-=.1)<0?s.display="none":setTimeout(fade,40)})();
                        

functional javascript

  • functions first class citizens
  • functions can take functions as parameters and return funtions
  • functions have no side-effects (global no state changing)

filter

  • filter iterates over an array (or array like structre) and calling a supplied function returns a new array of elements identified by the function as passing
[0,1,2,3,4,5].filter(function(v){return v > 2}); // [3,4,5]
                        

map

  • map iterates over an array and applies a function to each memeber. Then it collects the results and return as a new array.
var times2 = function(v){return v * 2};
[0,2,4,8,16].map(times2); // [0, 4, 8, 16, 32]
                        

reduce

  • applies a function to reduce an array to one value. the reduce callback takes parameters of the previous value (or the value so far), current value, index and the array
var sum = function(p, c, i){console.log('p:['+p+'];c:['+c+'];i:['+i+']');return p + c};
[0,2,4,8,16].reduce(sum); // 30 
var max = function(p, c, i){console.log('p:['+p+'];c:['+c+'];i:['+i+']');return c > p ? c : p};
[0,2,4,8,16].reduce(max); // 16
var grouper = function(p, c, i){console.log('p:['+p+'];c:['+c+'];i:['+i+']');p[c]= (p[c]||0) + 1;return p};
[0,2,4,8,16,8,4,2].reduce(grouper,{}); // 16 
                        

mapreduce

  • combines several functional principles to allow distributed processing and a mass scale
  • map and reduce functions doesn't use shared state
  • mapper and reducers "emit" results as they go
  • map reduce systems allow passing intermediate results between nodes