4-51 Functional Programming

  • 利用first class function 特性,將function當成參數傳入另一個function 或回傳一個function
  • 盡量減少funciton side-effect,不更改原變數,不依賴全域變數 -> 每次function執行,結果都要相同
selfdefined map function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

function mapForEach(arr, fn) {

var newArr = [];
for (var i=0; i < arr.length; i++) {
newArr.push(
fn(arr[i])
)
};

return newArr;
}

var arr1 = [1,2,3];
console.log(arr1);


var arr2 = mapForEach(arr1, function(item) {
return item * 2;
});
console.log(arr2);


var arr3 = mapForEach(arr1, function(item) {
return item > 2;
});
console.log(arr3);


var checkPastLimit = function(limiter, item) {
return item > limiter;
}
var arr4 = mapForEach(arr1, checkPastLimit.bind(this, 1));
console.log(arr4);


var checkPastLimitSimplified = function(limiter) {
return function(limiter, item) {
return item > limiter;
}.bind(this, limiter);
};

var arr5 = mapForEach(arr1, checkPastLimitSimplified(1));
console.log(arr5);

4-51 Functional Programming

  • Read code of open source library
  • underscore.js
  • lodash.js

Comment and share

4-50 call(), apply(), and bind()

bigword alert : Function currying

  • creating a copy of a function but with some preset parameters.

  • The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.REF


bind 複製function,並將其中的 this 設成給定的物件,回傳複製的function

  • The call() method calls a function with a given this value and arguments provided individually.REF

call 將function中的this改為thisArg, 並用後面的參數invoked 該function

  • The apply() method calls a function with a given this value and arguments provided as an array REF

apply和call功能相同,差別只有function的參數要用array傳入

1
2

fun.call(thisArg[, arg1[, arg2[, ...]]])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

var person = {
firstname = 'John';
lastname = 'Doe';
getFullName : function(){
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
}

var logName = function(lang1,lang2){
console.log('Logged : ' + this.getFullName());
console.log('Arguments: ' + lang1 + ' ' + lang2);
}

var logPersonName = logName.bind(person);
logName();
logName.call(person,'en','es');
logName.apply(person,['en','es']);

When is this used in real life?

  • function borrowing
function borrowing
1
2
3
4
5
6

var person2 = {
firstname : 'Jane';
lastname : 'Doe';
}
person.getFullName.apply(person2);
  • function currying
function currying
1
2
3
4
5
6
7

function multiply(a,b){
return a * b;
}
var multiplyByTwo = multiply.bind(this,2);
// set first parameter(a) = 2, reutrn a new copy of multiply function
console.log(multiplyByTwo(4));

Comment and share

4-46 Understanding Closures

  • why whattosay is still exist when invoking sayHi ?

  • greet function is pop off the execution stack, so whattosay should be clear.

  • Closures: closing in all variables that the function supposed to have access to

  • the execution context has closed in its outer environment reference(only variables, not values), even though those outer execution contexts are gone.

1
2
3
4
5
6
7
8
9

function greet(whattosay){
return function(name){
console.log(whattosay + ', ' + name);
}
}
greet('Hey')('Necisam');//Hey, Necisam
var sayHi = greet('Hey');// a function
sayHi('Necisam');

4-47 Understanding Closures part2

Closures close only the variables, not the values.

  • Free variables : it is outside a function, but that you have access to.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

function buildFunctions(){
var arr = [];
for(var i = 0; i < 3; i++){
arr.push(
function(){
console.log(i);
}
);
}
return arr;
}
var fs = buildFunctions();
fs[0]();
fs[1]();
fs[2]();
// 3 3 3
// i is set to 3 after the loop
//

to execute the functions to get different execution context that contains different J s.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function buildFunctions(){
var arr = [];
for(var i = 0; i < 3; i++){
arr.push(
(function(j){
return console.log(j);
}(i))
);
}
return arr;
}
var fs = buildFunctions();
fs[0]();
fs[1]();
fs[2]();

ES6 solution

  • let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used.
  • each j would be a new variables in mem(just like c language)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

function buildFunctions(){
var arr = [];
for(var i = 0; i < 3; i++){
let j = i;
arr.push(
function(){
console.log(j);
}
);
}
return arr;
}
var fs = buildFunctions();
fs[0]();
fs[1]();
fs[2]();

4-48 Funciton factories

  • Every time the function be invoked, a new execution context is created.
  • This lets us create functions from other functions.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

function makeGreeting(language){
return function(firstname,lastname){
if(language === 'en'){
console.log('Hello '+ firstname + lastname);
}
if(language === 'es'){
console.log('Hola' + firstname + lastname);
}
}
}

var gEnglish = makeGreeting('en');
var gSpanish = makeGreeting('es');
gEnglish('YuCheng','Cheng');
gSpanish('YuCheng','Cheng');

4-49 Closures and Callbacks

bigword alert : Callback funcion

  • A function you give to another function, to be run when the other function is finished
1
2
3
4
5
6
7
8
9
10

function sayHiLater(){
var greeting = 'Hi!';

setTimeout(functions(){
console.log.(greeting);
}, 3000);
}

sayHiLater();

Comment and share

4-43 White space

4-44 Immediately invoked function expressions(IIFEs)

function 被宣告後馬上被執行,回傳hello字串給greeting

IIFEs
1
2
3
4
5

var greeting = function (name){
return ('Hello ' + name);
}('Necisam');
//greeting hold the string returned by function

syntax parse saw function keyword in the starting in a line, it expects that this is a function statement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

3;// an expression

// an expressions
{
name : "necisam",
country : "Taiwan"
}

// expressions
function (name){
return "Hello " + name;
}

//to trick syntax parser, make it become an expression
//parenthesis is a operator in JS
(function (name){
return "Hello " + name;
});

//invoke a function expression !!
(function (name){
return "Hello " + name;
}('Necisam'));

4-45 IIFEs and safe code

因為是呼叫function,有自己的 execution context
所有function 不會動到 global
如果真的需要global的內容,下面給了一個範例
能夠安全的access global content

1
2
3
4
5
6
7
8
9
10
11

var greeting = 'Hola';

// objects are passed by reference
(function (global, name){
var greeting = 'Hello';
global.greeting = 'Hello';
console.log(greeting + ' ' + name);
}(window, 'Necisam'));

console.log(greeting);//Hello, modfied by function

Comment and share

4-34 Functions are Objects

bigword alert : FIRST CLASS FUNCTIONS

  • every things you can do with other types you can do with functions.
  • assignthem to variables, pass them around, create them on the fly.
  • js is not the only language that has first class function

function has more properties than object

  • Name(optional)
  • Code
  • use () to invoke a function

My helpful screenshot

Functions are Objects
1
2
3
4
5
6
7

//declare a function
function greet(){
console.log('hi');
}

greet.languague = "English"; //add property to function!!!

#4-35 Function statements and function Expressions

bigword alert : Expression

  • a unit of code that results in a value
  • statement just do the work
function express vs statement
1
2
3
4
5
6
7
8
9
10
11
12
13

greet();

//function statement
function greet(){
console.log('hi');
}

//function express, return a object to var
var anonymousGreet = function (){
console.log('hi');
}
anonymousGreet(); //use () to invoke a function
function hoisting
1
2
3
4
5

anonymousGreet(); //error : anonymousGreet is undefined this line
var anonymousGreet = function (){ //anonymousGreet is set to a function
console.log('hi');
}
pass function as parameter
1
2
3
4
5
6
7
8

function log(a){
console.log(a);
}

log(function (){
console.log('hi');
});

#4-36 By value and By reference

  • In js, primitives are by value
  • In js, objects(includes functions) are by reference
  • 沒有選擇餘地,就是這樣

by value

My helpful screenshot

by reference

My helpful screenshot

bigword alert : Mutate

  • to change sth
  • Immutable means it can’t be changed
by value/reference
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

// by value (primitives)
var a = 3;
var b;

b = a;
a = 2;

console.log(a);
console.log(b);

// by reference (all objects (including functions))
var c = { greeting: 'hi' };
var d;

d = c;
c.greeting = 'hello'; // mutate

console.log(c);
console.log(d);

// by reference (even as parameters)
function changeGreeting(obj) {
obj.greeting = 'Hola'; // mutate
}

changeGreeting(d);
console.log(c);
console.log(d);

// equals operator sets up new memory space (new address)
c = { greeting: 'howdy' };
console.log(c);
console.log(d);

#4-37 Object, functions,and this

  • ‘this’ is depending on how the funciton is called
  1. In the global execution context -> global object
  2. In function context, simple call (ex : f1() ) -> global object
  3. As an object method -> the object

whole document

what is this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

console.log(this);// window

function a (){
console.log(this);
}
a()// window

var b = function(){
console.log(this);
}

b()//window

var c = {
name:"the c object",
log: function(){

this.name = "updated c object";
console.log(this);//c object

var setname = function(newname){
this.name = newname;// the global object ,windows!!!
// a lot of people think it's wrong
}
setname('updated again!!');
console.log(this); //c object with name : "updated c object"
}
}
c.log();
tips avoiding weird this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

var c = {
name:"the c object",
log: function(){
var self = this; //save this(c object) address in var self

self.name = "updated c object";
console.log(self);

var setname = function(newname){
self.name = newname;// self point to the c objects
}
setname('updated again!!');
console.log(self);
}
}
c.log();

4-38 Array-collection of anything

  • In javascript, array is typeless. You can put anything into it(Even a function = special object).
array contains everything
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

var arr = [
1,
true,
{
name:'sam',
phone:'0911111111'
},
function (name){
var greeting = 'Hello ';
console.log(greeting + name);
},
"bello"
]
arr[3](arr[2].name); // "Hello sam"

4-39 arguments and spreads

  • arguments keyword contains all the function arguments
  • arguments is array-like, not exactly regular array
  • arguments will become deprecated
  • spread parameter(…) //資料查到是叫Rest parameters
use arguments
1
2
3
4
5
6
7
8

function greet(firstname,lastname,language){
console.log(arguments);
console.log(firstname);
console.log(lastname);
console.log(language);
}
greet() // undefined undefined undefined
spreadparams
1
2
3
4

function greet(firstname,lastname,language, ...other){
// additional params are put into an array called other
}

4-40 function overloading

  • js don’t have function overloading
  • In js, funtion is an object
  • In js, there are firstclass function
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

function greet(firstname, lastname, language) {
language = language || 'en';
if (language === 'en') {
console.log('Hello ' + firstname + ' ' + lastname);
}
if (language === 'es') {
console.log('Hola ' + firstname + ' ' + lastname);
}
}
function greetEnglish(firstname, lastname) {
greet(firstname, lastname, 'en');
}
function greetSpanish(firstname, lastname) {
greet(firstname, lastname, 'es');
}
greetEnglish('John', 'Doe');
greetSpanish('John', 'Doe');

Comment and share

Author's picture

Necisam

author.bio


author.job


Tainan, Taiwan