JavaScript in-depth
Why JS?
Complex web apps

"...There isn't any point to diving into new technologies, or using the hottest libraries, if you don't have a proper understanding of the fundamental characteristics of the JavaScript language"
-John Resig, Secrets of the JavaScript Ninja
In short: beware of JS script kiddies
1. So, JavaScript will be relevant forever.
2. JavaScript lives in other environments outside of browsers (Windows 8, Node Js, Firefox Os, GNOME)
You can program hardware in JavaScript tessel.io
Summary
Javascript enlightment:
* Language Background * Syntax * Primitive values * JavaScript Objects * Function() * Scopes, Environments, Hoisting and Closures * Promises * Functional programmingAdditional:
* JSHint * Devtools DebuggerNot covered:
* Frameworks (AngularJS, Backbone, etc) * Modern front-end development tools (grunt, node, requireJS, bower, etc.) * DOM manipulation * High performance applications
COnsole up!
Firebug
Assumptions:
- You already know how to program
- You already know (at least) OOP
- You have a slight idea of what JavaScript is for
Background

JavaScript Versus ECMAScript
* BTW WE'LL TALK ONLY about ECMASCRIPT 5
* BTW WE'LL TALK ONLY about ECMASCRIPT 5
Brendan eich's influences:
-
Java (syntax, primitive values versus objects)
-
Scheme and AWK (first-class functions)
-
Self (prototypal inheritance)
-
Perl and Python (strings, arrays, and regular expressions)
Syntax
// Two slashes start single-line comments
var x; // declaring a variable
x = 3 + y; // assigning a value to the variable `x`
foo(x, y); // calling function `foo` with parameters `x` and `y`
obj.bar(3); // calling method `bar` of object `obj`
// A conditional statement
if (x === 0) { // Is `x` equal to zero?
x = 123;
}
// Defining function `baz` with parameters `a` and `b`
function baz(a, b) {
return a + b;
}
Identifiers and Variable Names
The first character of an identifier can be any Unicode letter, a dollar sign ($), or an underscore (_). Subsequent characters can additionally be any Unicode digit. Thus, the following are all legal identifiers:
arg0
_tmp
$elem
π
Statement vs Expressions
if (condition) {
}
3 + 4
Primitive values
-
Booleans: true, false
-
Numbers: 1736, 1.351
-
Strings: 'abc', "abc"
-
Two “nonvalues”: undefined, null (see undefined and null)
Primitives have the following characteristics:
Compared by value
> 3 === 3
true
> 'abc' === 'abc'
true
ALWAYS IMMUTABLE
Properties can’t be changed, added, or removed:
> var str = 'abc'; > str.length = 1; // try to change property `length` > str.length // ⇒ no effect 3 > str.foo = 3; // try to create property `foo` > str.foo // ⇒ no effect, unknown property undefined
Objects
All nonprimitive values are objects. The most common kinds of objects are:
Plain objects
{
firstName: 'Jane',
lastName: 'Doe'
}
Arrays
[ 'apple', 'banana', 'cherry' ]
Regular expressions
/^a+b+$/
Compared by reference
Identities are compared; every value has its own identity:
> {} === {} // TWO DIFFERENT EMPTY OBJECTS
FALSE
> VAR OBJ1 = {};
> VAR OBJ2 = OBJ1;
> OBJ1 === OBJ2
TRUE
> {} === {} // TWO DIFFERENT EMPTY OBJECTS
FALSE
> VAR OBJ1 = {};
> VAR OBJ2 = OBJ1;
> OBJ1 === OBJ2
TRUE
MUTABLE BY DEFAULT
You can normally freely change, add, and remove properties:
> VAR OBJ = {};
> OBJ.FOO = 123; // ADD PROPERTY `FOO`
> OBJ.FOO
123
Object literal vs constructors
var arr = [1, 2, 3]; //Literal notation
var arr2 = new Array(); //Using contructors
arr2.push(1);
arr2.push(2);
arr2.push(3);
undefined and null

...and null
Truty and faLsy
-
undefined, null
-
Boolean: false
-
Number: -0, NaN
-
String: ''
Type Coercion
Type coercion means the implicit conversion of a value of one type to a value of another type.
> '3' * '4'
12
> 3 + ' times'
'3 times'
Functions for Converting to Boolean, Number, String, and Object
More stuff
Binary logic operators: &&, ||
Function()
function add(param1, param2) {
return param1 + param2;
}
var add = function (param1, param2) {
return param1 + param2;
};
Variables Are Function-Scoped
function foo() {
var x = -512;
if (x < 0) { // (1)
var tmp = -x;
...
}
console.log(tmp); // 512
}
Closures
function createIncrementor(start) {
return function () { // (1)
start++;
return start;
}
}
uh?
> var inc = createIncrementor(5);
> inc()
6
> inc()
7
> inc()
8
The IIFE
(function () { // open IIFE
var tmp = ...; // not a global variable
}()); // close IIFE
-
Auto-execute a function
-
Introducing a New Scope
-
Avoid inadvertent sharing via closures
Constructors: Factories for Objects
// Set up instance data
function Point(x, y) {
this.x = x;
this.y = y;
}
// Methods
Point.prototype.dist = function () {
return Math.sqrt(this.x*this.x + this.y*this.y);
};
> var p = new Point(3, 5);
> p.x
3
> p.dist()
5.830951894845301
The Prototype Relationship Between Objects

Prototype chain
var PersonProto = {
describe: function () {
return 'Person named '+this.name;
}
};
var jane = {
[[Prototype]]: PersonProto,
name: 'Jane'
};
var tarzan = {
[[Prototype]]: PersonProto,
name: 'Tarzan'
};
[[Prototype]] is an invented syntax. In some engines you can use __proto__ (“dunder proto")
> jane.describe()
Person named Jane
> tarzan.describe()
Person named Tarzan
Constructors—Factories for Instances
function Person(name) {
this.name = name;
}
Person.prototype.describe = function () {
return 'Person named '+this.name;
};
> var jane = new Person('Jane');
> jane.describe()
'Person named Jane'
OOP?
“Object-oriented programming is an exceptionally bad idea which could only have originated in California.” — Edsger Dijkstra
“object-oriented design is the roman numerals of computing.” — Rob Pike
“The phrase "object-oriented” means a lot of things. Half are obvious, and the other half are mistakes.“ — Paul Graham
Class-oriented 00 vs. Prototypal OO
http://ericleads.com/2013/06/classical-inheritance-is-obsolete-how-to-think-in-prototypal-oo/
Promises!

CALLBACK HELL
var results = doThis(function(data) {
doThat(data, function(data2) {
mungeNumbers(data2, function(data3) {
hideTracks(data3, function(data4) {
boostProfits(data4, function(data5) {
// On, and on, and on and on...
})
})
})
})
})
PromiseS
var promise = new Promise(function(resolve, reject) {
resolve(1);
});
promise.then(function(val) {
console.log(val); // 1
return val + 2;
}).then(function(val) {
console.log(val); // 3
});
Functional programming
IDENTIFICATION DIVISION.
PROGRAM-ID. chgmaker.
DATE-WRITTEN. 1/28/2013.
* AUTHOR Dr_Legacy
* REMARKS reddit dailyprogrammer challenge #119
ENVIRONMENT DIVISION.
CONFIGURATION SECTION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
DATA DIVISION.
FILE SECTION.
WORKING-STORAGE SECTION.
01 AMOUNT-IN PIC X(10).
01 NFRAC PIC X(5).
01 NFRAC9 REDEFINES NFRAC PIC 9(5).
01 N1 PIC X(10).
01 N2 PIC X(10) VALUE ZEROS.
01 N29 REDEFINES N2 PIC 9(10).
01 CHARCOUNT PIC 99 VALUE ZERO.
01 CC2 PIC 99 VALUE ZERO.
01 AMOUNT-WORKING PIC 9(11)V99.
01 QUARTER-VALUE PIC 9V99 VALUE 0.25.
01 DIME-VALUE PIC 9V99 VALUE 0.10.
01 NICKEL-VALUE PIC 9V99 VALUE 0.05.
01 PENNY-VALUE PIC 9V99 VALUE 0.01.
01 QUARTER-COUNT PIC 9(11) VALUE ZERO.
01 DIME-COUNT PIC 9 VALUE ZERO.
01 NICKEL-COUNT PIC 9 VALUE ZERO.
01 PENNY-COUNT PIC 9 VALUE ZERO.
01 AMOUNT-OUT PIC Z(10)9.
*****
PROCEDURE DIVISION.
*****
MAIN-LOGIC SECTION.
MAIN-BEGIN.
DISPLAY "CHANGE MAKING PROGRAM".
DISPLAY "ENTER AMOUNT".
ACCEPT AMOUNT-IN.
IF AMOUNT-IN EQUAL SPACE THEN
GO TO EXIT-PROGRAM.
*** old COBOL doesn't have any really fancy string functions
UNSTRING AMOUNT-IN
DELIMITED BY ALL SPACES
OR "."
INTO N1, NFRAC.
INSPECT NFRAC REPLACING ALL SPACE BY ZERO.
COMPUTE AMOUNT-WORKING ROUNDED = NFRAC9 / 100000 .
IF N1 NOT EQUAL SPACE THEN
PERFORM VARYING CHARCOUNT FROM 10 BY -1
UNTIL N1(CHARCOUNT:1) NOT = SPACE
*** reference modification. YOU KIDS HAVE IT EASY I TELL YOU
END-PERFORM
COMPUTE CC2 = 10 - CHARCOUNT + 1
STRING N1(1:CHARCOUNT) DELIMITED SIZE INTO N2
POINTER CC2
ADD AMOUNT-WORKING N29 GIVING AMOUNT-WORKING
.
DISPLAY "".
DIVIDE AMOUNT-WORKING BY QUARTER-VALUE
GIVING QUARTER-COUNT
REMAINDER AMOUNT-WORKING.
IF QUARTER-COUNT IS GREATER THAN ZERO
MOVE QUARTER-COUNT TO AMOUNT-OUT
DISPLAY "QUARTERS: " AMOUNT-OUT.
DIVIDE AMOUNT-WORKING BY DIME-VALUE
GIVING DIME-COUNT
REMAINDER AMOUNT-WORKING.
IF DIME-COUNT IS GREATER THAN ZERO
MOVE DIME-COUNT TO AMOUNT-OUT
DISPLAY "DIMES: " AMOUNT-OUT.
DIVIDE AMOUNT-WORKING BY NICKEL-VALUE
GIVING NICKEL-COUNT
REMAINDER AMOUNT-WORKING.
IF NICKEL-COUNT IS GREATER THAN ZERO
MOVE NICKEL-COUNT TO AMOUNT-OUT
DISPLAY "NICKELS: " AMOUNT-OUT.
DIVIDE AMOUNT-WORKING BY PENNY-VALUE
GIVING PENNY-COUNT
REMAINDER AMOUNT-WORKING.
IF PENNY-COUNT IS GREATER THAN ZERO
MOVE PENNY-COUNT TO AMOUNT-OUT
DISPLAY "PENNIES: " AMOUNT-OUT.
IF AMOUNT-WORKING IS GREATER THAN ZERO
DISPLAY "wtf ".
MAIN-END-PROGRAM.
GO TO EXIT-PROGRAM.
MAIN-EXIT.
EXIT.
/
DRLEGACY-MISC SECTION.
EXIT-PROGRAM.
EXIT PROGRAM.
...
function coins(amount) {
return [25, 10, 5, 1].map(function(coin) {
return [~~(amount / coin), amount %= coin][0];
});
}
Recommended readings
"Secrets of the JavaScript Ninja", John Resig and Bear Bibeault
JavaScript in-depth
By Erick Mendoza
JavaScript in-depth
- 1,994