webdev-js



webdev-js

1 0


webdev-js

JavaScript: the bad parts

On Github pp2-ex / webdev-js

Intro to web development

Part II: ECMAScript

seb@wilzba.ch

Design flaws

  • global variables var
  • single-threaded (➙ WebWorker)
  • ...

Type coersion

'' == '0'          // false
0 == ''            // true
0 == '0'           // true

false == 'false'   // false
false == '0'       // true
true == '1'        // true

false == undefined // false
false == null      // false
null == undefined  // true

' \t\r\n ' == 0    // true
➙ always use ===

== is weakly-typed and slower than ===

NAN

NaN === NaN    // false
NaN !== NaN   // true

null and undefined

typeof null;       // object
typeof undefined;  // undefined

Javascript type table

Value               Class      Type
-------------------------------------
"foo"               String     string
new String("foo")   String     object
1.2                 Number     number
new Number(1.2)     Number     object
true                Boolean    boolean
new Boolean(true)   Boolean    object
new Date()          Date       object
new Error()         Error      object
[1,2,3]             Array      object
new Array(1, 2, 3)  Array      object
new Function("")    Function   function
/abc/g              RegExp     object (function in Nitro/V8)
new RegExp("meow")  RegExp     object (function in Nitro/V8)
{}                  Object     object
new Object()        Object     object

useful:

typeof foo !== 'undefined'

Instanceof

with native types:

new String('foo') instanceof String; // true
new String('foo') instanceof Object; // true

'foo' instanceof String; // false
'foo' instanceof Object; // false

➙ use instanceof only for custom objects

new Bar() instanceof Foo; // true

Semicolon insertion

function(){
    return
    1 + 2
}

function(){
    return;
    1 + 2;
}

➙ always use ;

Block-less JS

if (true)
 doThis()
 doThat()

if (true) {
 doThis();
}
doThat();

Iterators

Simple for loop

for(var i = 0; i < arr.length; i++){
    console.log(arr[i]);
}

forEach

arr.forEach(function(entry){
    console.log(entry);
});

for-in

for(var key in arr){
    console.log(arr[key]);
}

Attention:

for-in

  • slow
  • enumerates all the properties on the prototype chain
if (arr.hasOwnProperty(key){

}

eval && void

  • eval

    • insecure
    • super inefficient

    • void(arg) ➙ undefined (useless)

Be aware:

setTimeout and setInterval accept strings and eval them internally.

with

  • unpredictable
  • slow
with (obj) {
    a = b;
}
a = b;
a = obj.b;
obj.a = b;
obj.a = obj.b;

this scope

var obj = {
 inner: "word",
 hi: function(name){
    console.log(this.inner, name);
 }
}

1,2) Method calls

obj.hi("rost"); // method call
var m = obj.hi;
m("rost")  // baseless method call  -> undefined

3,4) Call, Apply

obj.hi.call({inner: "bword"}, "rost");
obj.hi.apply(obj, ["rost"]);

CS / ES6: =>

this scope

5) Constructor

var obj = function(){
 this.inner = "word"
 this.hi = function(name){
    console.log(this.inner, name);
 }
}

new obj.hi()

Scope tricks

  • bind the scope
method.bind(instance);
  • save the scope
function(){
    var self = this;
    foo.on("click", function(evt){
        console.log(this,self);
    }
}

Hoisting

x = 5; // Assign 5 to x

elem = document.getElementById("demo"); // Find an element 
elem.innerHTML = x;                     // Display x in the element

var x; // Declare x

(only for var declarations)

Other pitfalls

  • new WebAPIs (e.g. FileAPI, LocalStorage, ... )
  • IE <= 10
  • setTimeout(..., 0) has a delay
  • new Date().getMonth() (0: January)
  • arguments
    • Array.prototype.slice.call(arguments)

Language rules

  • always
    • var
    • ;
  • no
    • eval,with
    • modification of builtin Objects (Object.prototype)
  • use sparingly
    • for-in (only for map/hash/associative arrays)
    • this (constructor, methods assignment)

Style tips

  • C++/Java rules
    • functionNamesLikeThis, variableNamesLikeThis, ClassNamesLikeThis
    • function () {
  • name your anounymous functions ➙ debugging
  • avoid new Object (➙ {}) && new Array(➙ [])

style guides

BE CONSISTENT

Events

  • trickling = capturing: root -> leaf
  • bubbling: leaf -> root

© yuiblog.com

Events

Callbacks

var fs = require('fs');

fs.readFile('file.txt', 'utf8', function(err, data) {
    if (err) throw err;     
    console.log('File has been read:', data);
});

Problems:

  • concurrency
  • callback hell

Events

Promises

asyncCall()
.then(function(data1){
    // do something...
    return anotherAsyncCall();
})
.then(function(data3){
   // the third and final async response
})
.fail(function(err) {
   // handle any error resulting from any of the above calls    
})
Q.all(evts).then(function(dat){
    // waited for all events to finish
});

+ Streams

Good parts

Functions as first-class citizens

var rost = {
    lab: function() { alert('hi'); }
}
rost.lab();

prototype inheritance

  • prototype property
  • constructor property

➙ Mixins

var yourMixins = {
    dummyMethod: function(){
        console.log("Hello world");
    }
}
_.extend( YourAwesomeClass.prototype, yourMixins);

Closures

function rost(name){
    var location = "munich";
    function lab(){
        return location + "-" + name;
    }
    return lab;
}
var f = rost("foo");
f(); // munich - foo
f.location = 'berlin';
f(); // berlin - foo

Functional programming

  • map
  • reduce
  • filter

➙ Underscore / Loadash

var arr = [0,1,2,3,4]; 
arr = arr.filter(function(el){ return el % 2 == 0 }); // [0,2,4]
arr = arr.map(function(el){ return el +1 }); // [1,3,5]
arr.reduce(function(memo,el){ // sum
    return memo + el;
}) // 9

JSON

JavaScript Object Notation

  • JSON.parse(obj)
  • JSON.stringify(obj)
"course": {
    "chair": "RostLab",
    teachers: ["Tatyana Goldberg", "Juan Miguel Cejuela"],
    "location": {
        "postcode": "85748",
        "city": "Garching"
    }
}

Node & NPM

CS & ES6

Iterators

var entry;
while (!(entry = arr.values().next()).done) {
    console.log(entry.value);
}

Performance

DOM reflows

happens when

  • When you add or remove a DOM node.
  • When you apply a style dynamically (e.g. element.style.width="10px")
  • When you retrieve a measurement that must be calculated (e.g. offsetWidth, clientHeight)

➙ avoid reflows (expensive operations!)

Performance tricks

more

Github