Function
Define a Function
<button type = "button" onclick="f()">Click</button>
<script type="text/javascript">
function f()
{
document.write("Hello World!");
}
</script>
Return
function f()
{
return Math.PI;
}
document.write(f());
Print the Function Definition
function f()
{
return Math.PI;
}
document.write(f); // Call without ()
Mutable & Immutable
Immutable for primitive types, boolean/Boolean, null, undefined, string/String, and number/Number
Mutable for Array, Function, and Object
// immutable
var a = 10;
console.log('Before Calling the Function: '+a); // 10
changeValue(a); // 100
console.log('After Calling the Function: '+a); // 10
function changeValue(v)
{
v *= 10;
console.log('Inside Function: '+v);
}
both string and String are immutable, even the type of String is object
var s_1 = "Hello World!"; // immutalbe
var s_2 = new String("Hello World!"); // immutable
console.log(s_1 == s_2); //true
console.log(s_1 === s_2); //false
function change(s)
{
s = s+"Changed";
}
change(s_1);
change(s_2);
console.log(s_1); // Hello World!
console.log(typeof(s_1)); //string
console.log(s_2); //String("Hello World!")
console.log(typeof(s_2)); //object
// mutable
function change(ob)
{
ob.name = 'Yanhua';
console.log(ob);
}
var a = {name: 'Lin', age: 39}
console.log(a); // {name: 'Lin', age: 39}
change(a); // {name: 'Yanhua', age: 39}
console.log(a); // {name: 'Yanhua', age: 39}
Anonymous Function
var f = function (a, b) {return a+b;}
console.log(f(10, 100));
Arrow Function
Immutable for primitive types, boolean/Boolean, null, undefined, string/String, and number/Number
Mutable for Array, Function, and Object
// regular function
function add_1(a, b)
{
return a+b;
}
console.log(add_1(1, 2));
// arrow function
add_2 = (a, b) =>
{
return a+b;
}
console.log(add_2(1, 2));
// single instruction in arrow function
add_3 = (a, b) => a+b;
console.log(add_3(1, 2));
With a regular function this represents the object that calls the function
this keyword always represents the owner that of the arrow function
<button id="btn_1">Button 1</button>
<button id="btn_2">Button 2</button>
<script type="text/javascript">
//The window own the function:
window.addEventListener("load", () => {console.log(this)}); // window
document.getElementById("btn_1").addEventListener("click", () => {console.log(this)}); // window
//The window object calls the function:
function info()
{
console.log(this);
}
window.addEventListener("load", info); // window
document.getElementById("btn_2").addEventListener("click", info); // button
</script>
Default Arguments
function f(a = 1, b = 2)
{
console.log(a+b);
}
f(10, 100); // 110
f(10); // 12
f(b = 10); // 12, 10 is assigned to a
Keyword Arguments
function f({a = 1, b = 2})
{
console.log(a+b);
}
f({a:10, b:100}); // 110
f({a:10}); // 12
f({b :10}); // 11
const add = ({a = 1, b = 2}) =>
{
console.log(a+b);
}
add({a:10, b:100}); // 110
add({a:10}); // 12
add({b:10}); // 12, 10 is assigned to a
Self-Invoking Function
A self-invoking expression is invoked (started) automatically, without being called
Function expressions will execute automatically if the expression is followed by ()
(function () {
var x = "Hello!!"; // I will invoke myself
})();
var loop = function() {
for(var x = 0; x < 5; x++) {
console.log(x);
}
}();
Arguments Object
function f()
{
if (arguments.length == 0) return 'undefined';
var min = arguments[0];
for(var i = 0; i < arguments.length; i++)
if (arguments[i] < min)
min = arguments[i];
return min;
}
console.log(f(-1, 0, 1, 2));
Rest Parameters
function f(p1, ...params)
{
console.log(p1);
for(let i = 0; i < params.length; i++)
console.log(params[i]);
}
f(1, 2, 3, 4)
call()
var person = {
info: function () {return this.name + " : " + this.age;},
setName: function (n) {this.name = n;}
}
var person1 = {name: 'Lin', age: 39};
var person2 = {name: 'Yanhua', age: 39};
person.setName.call(person1, 'Yanhua');
console.log(person.info.call(person1));
console.log(person.info.call(person2));
apply()
The call() method takes arguments separately
The apply() method takes arguments as an array
var a = [1, 2, 3];
console.log(Math.max.apply(null, a)); // apply Math.max() method to array
Closure
Is assigned the return value of a self-invoking function
It can access the counter in the parent scope
<button type="button" onclick="myFunction()">Count!</button>
<p id="demo">0</p>
<script>
var add = (function () {
var counter = 0;
return function () {counter += 1; return counter;}
})();
function myFunction(){
document.getElementById("demo").innerHTML = add();
}
</script>
Recursive
const fact = (n) =>
{
if (n == 1)
return n;
else
return n*fact(n-1);
}
console.log(fact(10));
Generator
function* g(n)
{
for(let i = 0; i < n; i++)
yield i;
}
for (e of g(10))
console.log(e);
Promises
Implement async programming in JavaScript
function divide (a, b)
{
var p = new Promise(function(resolve, reject)
{
// do a thing, possibly async , then..
if(b == 0)
reject(Error("Denominator is Zero ..."));
else
resolve(a/b);
});
return p;
}
divide(10, 2).then(function(result)
{console.log("Result: "+result);},
function(error)
{console.log("Error: "+error);}
);
divide(6, 0).then(function(result)
{console.log("Result: "+result);},
function(error)
{console.log("Error: "+error);}
);
XMLHttpRequest
- request = new XMLHttpRequest(), synchronous and asynchronous
- request.open(method, URL, [async, user, password])
- xhr.send([body], GET do not have a body, POST use body to send the data to the server
- Listen to request events for response
- load – when the request is complete (even if HTTP status is like 400 or 500), and the response is fully downloaded
- error – when the request couldn’t be made
- progress – triggers periodically while the response is being downloaded, reports how much has been downloaded
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
const getFakeMembers = count => new Promise((resolves, rejects) => {
const api = `https://api.randomuser.me/?nat=US&results=${count}`
const request = new XMLHttpRequest()
request.open('GET', api)
request.onload = () =>
(request.status === 200) ?
resolves(JSON.parse(request.response).results) :
reject(Error(request.statusText))
request.onerror = (err) => rejects(err)
request.onprogress = function(event) { // triggers periodically
console.log(`Received ${event.loaded} of ${event.total}`);};
request.send()
})
getFakeMembers(1).then(
resolves = (members) => console.log(members),
rejects = (err) => {
console.error(new Error("cannot load members from randomuser.me"));
console.log(err)
}
)
</script>
</body>
</html>
Chaining
var promise = job1();
promise
.then(function(data1) {
console.log('data1', data1);
return job2();
})
.then(function(data2) {
console.log('data2', data2);
return 'Hello world';
})
.then(function(data3) {
console.log('data3', data3);
});
function job1() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('result of job 1');
}, 1000);
});
}
function job2() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('result of job 2');
}, 1000);
});
}
Functional Programming
JavaScript is a functional language because its functions are first-class citizens
Functions can be saved, retrieved, or flow through applications just like variables
Declarative programming is a style of programming where applications are structured in a way that prioritizes describing what should happen over defining how it should happen
Immutability
let color_lawn = {
title: "lawn",
color: "#00FF00",
rating: 0
}
//mutable
function rateColor(color, rating) {
color.rating = rating
return color
}
console.log(rateColor(color_lawn, 5).rating); //5
console.log(color_lawn.rating); //5
//immutable
function rateColor_2(color, rating){
return Object.assign({}, color, {rating:rating}) //Object.assign() merges all objects you pass it into the first one
}
console.log(rateColor_2(color_lawn, 10).rating); //10
console.log(color_lawn.rating); //5
//or arrow function with spread operator
const rateColor_3 = (color, rating) => ({...color, rating})
console.log(rateColor_3(color_lawn, 100).rating); //100
console.log(color_lawn.rating); //5
let list=[
{ title: "Rad Red"},
{ title: "Lawn"},
{ title: "Party Pink"}
]
//mutable
var addColor = function(title, colors) {
colors.push({ title: title })
return colors;
}
console.log(addColor("Glam Green", list).length); //4
console.log(list.length); //4
//immutable
var addColor_3 = (title, colors) => colors.concat({title})
console.log(addColor_3("Blue", list).length); //5
console.log(list.length); //4
//or with spread operator
var addColor_2 = (title, colors) => [...colors, {title}]
console.log(addColor_2("Red", list).length); //5
console.log(list.length); //4
Pure Function
- a function that returns a value that is computed based on its arguments
- do not cause side effects, set global variables, or change any‐ thing about application state
- treat their arguments as immutable data
const frederick = {
name: "Frederick Douglass",
canRead: false,
canWrite: false
}
const selfEducate = person => ({
...person,
canRead: true,
canWrite: true
})
console.log( selfEducate(frederick) )
console.log( frederick )
// {name: "Frederick Douglass", canRead: true, canWrite: true}
// {name: "Frederick Douglass", canRead: false, canWrite: false}
Data Transformations
remove an item from an array we should use Array.filter over Array.pop or Array.splice because Array.filter is immutabl
const schools = [ "Yorktown", "Washington & Lee", "Wakefield"]
const wSchools = schools.filter(school => school[0] === "W");
console.log( wSchools )
// ["Washington & Lee", "Wakefield"]
const schools = [ "Yorktown", "Washington & Lee", "Wakefield"]
const highSchools = schools.map(school => `${school} High School`);
console.log(highSchools.join("\n")
// Yorktown High School
// Washington & Lee High School
// Wakefield High School
const schools = [ "Yorktown", "Washington & Lee", "Wakefield"]
const highSchools = schools.map(school => ({ name: school }));
console.log( highSchools )
// [
// { name: "Yorktown" },
// { name: "Washington & Lee" },
// { name: "Wakefield" }
// ]
higher-order functions
const createScream = logger => message => logger(message.toUpperCase() + "!!!");
const scream = createScream(message => console.log(message));
scream('functions can be returned from other functions')
recursive
const countdown = (value, fn) => {
fn(value)
return (value > 0) ? countdown(value-1, fn) : value
}
countdown(10, value => console.log(value));
Composition
const template = "hh:mm:ss tt"
const clockTime = template.replace("hh", "03")
.replace("mm", "33")
.replace("ss", "33")
.replace("tt", "PM")
console.log(clockTime)
Helper Function
A helper function is a function help another function
function helper(num)
{
return help(num+5);
}
function help(num)
{
console.log(num);
}
helper(5);
Reference