Created by Christian Köberl
var i = 4;function myFunc() {
var i, greeting = 'Hello ';
for(i = 0; i < 10; i++) {
console.log(greeting + i);
}
}
function bench() {
// this is an infinite loop!
for(var i = 0; i < 1000; i++) {
for(var i = 0; i < 10; i++) {
var u = i * 10;
}
// u is still in scope here
console.log(u);
}
}
var x = 5
3
x // 5
var y = 5
+ 3
y // 8
var z = 5
(3) // TypeError: number is not a function
; at the end of statements=== (!==) to compare stuff== (!=) does type coercion'' == '0' // false
0 == '' // true
0 == '0' // true
false == 'false' // false
false == '0' // true
false == undefined // false
false == null // false
null == undefined // true
Number class/prototype0.1 + 0.2 !== 0.3
0.1 + 0.2 === 0.30000000000000004amount * 100amount / 100with(user) {
// read to user.name or global variable 'name'?
var userName = name;
// write user.password if user has password
// otherwise global variable 'password' :(
password = generatePwd(userName);
}
// create a function and a variable
function func1(arg1, arg2) {
...
return x;
}
// same can be achieved with
var func2 = function(arg1) {
...
}
// execute anoynmous function
(function () {
...
}());
arguments is an array-like structurearguments inherits from Arrayarguments.lengthis count of arguments passedarguments! Only read-access.// ES5
function sum() {
return arguments.reduce(function(x, y) {
return x + y;
});
}
myFunction(); // function form
myObject.myFunction(); // method form
new MyFunction(); // constructor form
myFunction.apply(thisObject, [arg1, arg2]); // apply/call form
myFunction.call(thisObject, arg1, arg2)
this?| Function form | global object (window),ES5: undefined |
|---|---|
| Method form | the object the method was called on |
| Constructor form | the object currently created |
| Apply/call form | the object passed as parameter |
var myThing = (function() {
var x = 42; // x is private
return {
// but can be accessed via getX
getX : function() { return x; }
};
}());
myThing.getX(); // 42
for(i = 0; i < elms.length; i++) {
elm = elms[i];
elm.onclick = function() {
elm.style.display = 'none'; // this will always be the last elm
return false;
}
}
⇒ never define functions in loops!
function hideHandler(elm) {
return function() {
elm.style.display = 'none';
return false;
};
}
for(i = 0; i < elms.length; i++) {
elm = elms[i];
elm.onclick = hideHandler(elm);
}
function calc(args, callback) {
var result = someComplexCalc(args);
callback(result);
}
calc(data, function(result) {
myObj.calculated = result;
});
Classical example: Prototype Ajax
new Ajax.Request('/your/url', {
onSuccess: function(response) {
// Handle the response content...
}
});
// encapsulated functions to be called only once
function once(func) {
return function() {
var f = func;
func = null;
return f.apply(this, arguments);
}
}
// now calc result can only be set once
calc(data, once(function(result) {
myObj.calculated = result;
}));
function add(x, y) {
return x + y;
}
function inc(x) {
return add(x, 1); // looks like currying
}
// real currying
Function.prototype.curry = function() {
var fn = this, args = Array.prototype.slice.call(arguments);
return function() {
return fn.apply(this, args.concat(
Array.prototype.slice.call(arguments)));
};
};
var inc2 = add.curry(1);
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(fn, scope) {
for (var i = 0, len = this.length; i < len; ++i) {
fn.call(scope, this[i], i, this);
}
}
}
function extend(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
var myMixin = {
clear : function() { return this.splice(0, this.legth); }
filter : function() { ... },
};
extend(Array.prototype, myMixin);
Objects are associative arrays
var myObj = {
fname : 'Christian',
lname : 'Köberl',
toString : function() {
return 'This is ' + this.lname.substring(0, 2);
}
};
myObj.fname; // 'Christian'
myObj['lname']; // 'Köberl'
myObj.toString(); // 'This is Kö'
myObj['toString']; // function() { return 'This is ' + ...
myObj.dateOfBirth = new Date();
myObj['lname'] = 'Muster';
// ES5 polyfill
if (!Object.hasOwnProperty('create') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
var newObj = Object.create(myObj);
newObj.toString(); // 'This is Kö'
newObj.toString = function() { return 'My ' + this.fname; }
newObj.toString(); // My Christian
function Person(id) {
this.id = id;
}
Person.prototype.toString = function() {
return 'Person (id=' + this.id + ')';
}
var p = new Person(5);
p.toString(); // Person (id=5)
function Person(id) {
this.id = id;
}
Person.prototype.toString = function() {
return 'Person (id=' + this.id + ')';
}
function Employee(id, employeeNo) {
this.id = id;
this.employeeNo = employeeNo;
}
Employee.prototype = new Person();
Employee.prototype.toString = function() {
return 'Employee (id=' + this.id + ', no=' + this.employeeNo + ')';
}
function createPerson(name) {
// private
var id = null;
function doGetId() {
return id || generateId();
}
// public (privileged)
return {
name: name,
getId : function() {
return doGetId();
}
}
}
function createEmployee(name, employeeNo) {
var that = createPerson(name);
that.toString = function() {
return 'Employee (name=' + that.name
+ ', no=' + employeeNo + ')';
}
return that;
}
var e = createEmployee('Christian', 42);
e.name = 'Hubert';
e.toString(); // Employee (name=Hubert, no=42)
var adder = (function() {
// private stuff
var calcCount = 0;
function doAdd(x, y) {
calcCount++;
return x + y;
}
// public stuff
return {
add : function(x, y) {
return doAdd(x, y);
},
calcCount : function() {
return calcCount;
}
};
}());
(function() {
// everything is private
var i, links = document.getElementsByTagName('a');
function createConfirmListener(link) {
return function() {
return confirm('Open link ' + link.href + '?');
}
}
// but we change global behaviour
for (i = 0; i < links.length; i++) {
links[i].onclick = createConfirmListener(links[i]);
};
}());
(function(global) {
// private stuff
var calcCount = 0;
function doAdd(x, y) {
calcCount += 1;
return x + y;
}
// public stuff
global.ADD_MODULE = {
add : function(x, y) {
return doAdd(x, y);
},
calcCount : function() {
return calcCount;
}
};
}(window));
// in math.js
MATH_MODULE = { calcCount : 0; };
// in add.js
MATH_MODULE.add = function(x, y) {
MATH_MODULE.calcCount += 1;
return x + y;
}
// in mult.js
MATH_MODULE.mult = function(x, y) {
MATH_MODULE.calcCount += 1;
return x * y;
}
define modules in JS filesrequire modules in main appdefine('pocoModule', ['dep1', 'dep2'], function (dep1, dep2) {
var priv1 = 'Hello';
function priv2 { ... }
...
// Define the module value by returning a value.
return function () {
publicVal : priv1 + ' World',
enhanceLink : function() { ... }
};
});
require(['jQuery', 'pocoModule'], function ($, poco) {
$('a').each(function() {
poco.enhanceLink($(this));
});
});
const length = 10; // length cannot be changed
for (let i = 0; i < length; i++) {
function geti() {
return i;
}
}
// i, geti are out of scope here
const inc = (a) => a + 1;
[1, 2, 3].map(inc).forEach((entry) => {
console.log(entry);
});
Arrow functions preserve this:
this.nums.forEach((num) => {
// this is the outer this :)
if (num > this.max) {
this.max = num;
}
});
const fullName = `${person.first} ${person.last}`
const multiLine = `Hello ${person.gender === 'M' ? 'Mr.' : 'Ms.'} ${fullName}!
Your car VIN is ${car.vin}.
Regards ${company.name}!`
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
fullName() {
return `${this.firstName} ${this.lastName}`;
}
get first() { return this.firstName; }
set first(firstName) { this._firstName = firstName; }
}
firstName is still public
const person = {
firstName: "Christian",
lastName: "Köberl",
fullName() { return `${this.firstName} ${this.lastName}`; }
}
let person = {
get firstName() { return "Christian" },
get lastName() { return "Köberl" },
fullName() { return `${this.firstName} ${this.lastName}`; }
}
fetch('/api/user') // returns a Promise
.then((response) => response.json())
.then(user => {
this.user = user;
});
// Create a promise
const inOneSecond = new Promise((resolve, reject) => {
setTimeout(() => resolve(`${msg} Hello ${who}!`), 1000);
});
inOneSecond.then(console.log);
async function load() {
const result = await fetch('/api/user');
return await response.json();
}
this.user = await load(); // this won't work, load returns a promise
(async () => {
this.user = await load();
})()