95
Tasting JavaScript Minimum Actionable Knowledge to be Skilled JSer Ken Chen

KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

Page 1: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Tasting JavaScript

Minimum Actionable Knowledge to be Skilled JSer

Ken Chen

Page 2: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Tasting JavaScriptMinimum Actionable Knowledge to be Skilled JSer

Ken Chen

© 2016 Ken Chen

Page 3: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Contents

I Hello World . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21.1 Environment Setup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4

II JavaScript Basics . . . . . . . . . . . . . . . . . . . . . . . . . 5

2. Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.1 Number . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.2 Special Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.3 String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.4 undefined & null . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.5 Boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.6 Automatic Type Coersion . . . . . . . . . . . . . . . . . . . . . . . . . . . 112.7 Conditional & Logical Operators . . . . . . . . . . . . . . . . . . . . . . . 12

3. Program Structure and Flow Control . . . . . . . . . . . . . . . . . . . . . . . 153.1 Expressions & Statements . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Convention . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17Refer, not contain . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18Default value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18Dynamic nature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

3.3 Run program file in Node.js . . . . . . . . . . . . . . . . . . . . . . . . . 193.4 Debug program file in Node.js . . . . . . . . . . . . . . . . . . . . . . . . 203.5 Control Flow . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

Conditional - if . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23Conditional - switch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25Loop - while . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26Loop - for . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28Loop Interruption - break . . . . . . . . . . . . . . . . . . . . . . . . . . 28Loop Interruption - continue . . . . . . . . . . . . . . . . . . . . . . . . 29

3.6 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

Page 4: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

CONTENTS

3.7 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31Triangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31Holed triangle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31Bing! Go! Bingo! Boom! . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

4. Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334.1 Definition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

Expression . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34Declaration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

4.2 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36Optional Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36Arguments Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36Parameters are keys, not boxes . . . . . . . . . . . . . . . . . . . . . . . 37

4.3 Scopes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 374.4 Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 394.5 Call Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 414.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

Any Sum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42Directory Printing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

5. Data Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 445.1 Object . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44Method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45The special this . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46Enumerate Properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48Mutability . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49

5.2 Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

5.3 Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52Object as Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52Native Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53

5.4 Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 545.5 String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

Interpolation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

5.6 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56Month Name Resolver . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56Array to Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57Matrix Convertor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57

6. Object-oriented . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 596.1 Core concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

Page 5: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

CONTENTS

6.2 Encapsulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60Constructor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60Getter and Setter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63Enumerable vs Non-enumerable . . . . . . . . . . . . . . . . . . . . . . 64

6.3 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65Prototype . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65Override . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67Self-defined inheritance relationship . . . . . . . . . . . . . . . . . . . . 69

6.4 Polymorphism . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 706.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

Whac-A-Mole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

7. Functional Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 757.1 Core concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75

First-class & Higher-order Function . . . . . . . . . . . . . . . . . . . . . 75Pure Function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76

7.2 Composition . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 777.3 Functional behaviors on Array . . . . . . . . . . . . . . . . . . . . . . . . 787.4 Closure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

Common Examples . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81Common Mistake . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84

7.5 Exercises . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87Array to Map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87Trampoline . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87Currying . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88

Page 6: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

I Hello World

Page 7: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

1. IntroductionMost good programmers do programming not because they expect to getpaid or get adulation by the public, but because it is fun to program. – LinusTorvalds

Tasting JavaScript is a book makes you learn JavaScript like tasting some food, bit bybit, enjoyable and memorable. But you might be wondering whether JavaScript is reallytasty and easy to digest because the rumor of it goes completely opposite.

Some people said that JavaScript is a language poorly designed andwritten in 7 days. Andyou can tell the gap between JavaScript: The Good Parts1 and JavaScript: The DefinitiveGuide2 from their sizes.

The Good Parts vs Definitive Guide

1https://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/05965177422https://www.amazon.com/JavaScript-Definitive-Guide-David-Flanagan/dp/0596101996

Page 8: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Introduction 3

However, many others are fancy about it because JavaScript is a so-called Full-Stacklanguage. It can be used in the browser to build an interactive web page, and also canbe used in the server side to operate database as a web server. What is more, you canuse it to build cross-platform desktop, or even a mobile application. JavaScript soundsso powerful and mysterious like Popeye the Sailor’s favorate spinach.

I can tell you that both are truth depending on your angle. In my opinion, JavaScript isnot difficult to digest (no complex development environment, nor compilation process)and tasty (funny to use it in plenty of areas). You have to try and make your own decisionregardless what others say.

1.1 Environment Setup

We’d better have our table set before the main course arrives.

There are two main environments for JavaScript to be executed, the browser and theserver. Although browser should be ready in everyone’s computer, it’s not friendlyenough for a JavaScript starter. So, I will choose Node.js3 as the environment for youto start tasting JavaScript. You don’t really need to figure out what it’s now.

For Windows & Mac users, the simplest way is to use the installer shown in homepage.For Linux user, since you are tough enough to use Linux, I think you should be able tofigure out your way to install it. You’d better choose the v6 LTS version which means it’sLong-term supported.

After the installation, please type node in the command line and you should be able tosee similar screen as below. It means you have entered the Node.js console already, it’sa playground and you can type in JavaScript statements there for execution. If you wantto leave, just press Ctrl+C (which means pressing Ctrl and C on your keyboard at thesame time), twice.

3http://nodejs.org/

Page 9: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Introduction 4

REPL

OK, you are all set already. Simple, right? In later chapters, when you are requested toinput some code, you just need to fire up this Node.js console in the command line andtype the code there. Let’s move on if you already want to try the course.

1.2 Exercises

Starting from chapter 3, there are some exercises at the end. Please try your best toaccomplish them before seeing the answer4.

4https://github.com/kenspirit/tasting-javascript-exercise

Page 10: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

II JavaScript Basics

Page 11: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

2. Data TypesI am not a great programmer; I am just a good programmer with great habits.– Kent Beck

Data/value to computer program is the ingredient to food. There are several basic datatypes in JavaScript, number, string, boolean, undefined, function and object. Object andFunction will be discussed in standalone chapters as they are so special and importantin JavaScript.

2.1 Number

A calculator might be the most commonly seen and basic form of computer in the olddays. How about we try to use JavaScript to do some numeric calculation first? Please tryto type 1 + 2 * 3 / 4 - 5 and press Enter in Node.js console.

1 -1 + 2 * 3 / 4 - 5

2 // -> -4.5

Notes: The two slashes and arrow are indicating the output of the program. They arenot part of the program. But even if you input that part in console, it makes no harm asanything after two slashes are treated as comment.

The symbols +, -, * and / are called operator. They can be used on numbers. + is foraddition, * is for multiplication, / is for division. - is for subtraction and also negatesa value. The order of applying these operators, determined by their precedence, alignswith the math we learn in school. If you want to ajust the order, parentheses () can beused.

1 -(1 + 2) * 3 / (4 - 5)

2 // -> 9

There is one more arithmetic operator %, called Modulus. It is used for remaindercalculation. X % Y calculates the remainder of dividing X by Y. For example, 10 % 3

produces 1. You can try it out combining with other operators to verify its precedence.

Page 12: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Types 7

2.2 Special Numbers

The computer we are using has such huge memory and fast CPU now. Have you everwonder how fast it calculates and what is themaximumnumber supported in JavaScript?Try below calculation by multiplying 987654321987654321987654321987654321 to itself eighttimes.

1 987654321987654321987654321987654321 * 987654321987654321987654321987654321 * 98\

2 7654321987654321987654321987654321 * 987654321987654321987654321987654321 * 9876\

3 54321987654321987654321987654321 * 987654321987654321987654321987654321 * 987654\

4 321987654321987654321987654321 * 987654321987654321987654321987654321

5 // -> 9.05398453661256e+287

Above result comes out can be roughly estimated as 9e+287 which means that there are287 zero after 9. Does it really has a maximum limit? Yes. You can type in below symbolto see the largest value supported in JavaScript.

1 Number.MAX_VALUE

2 // -> 1.7976931348623157e+308

So what happen if you try to plus 1 on it?

1 Number.MAX_VALUE + 1

2 // -> 1.7976931348623157e+308

Seems nothing happen. Actually, in JavaScript, when you hit some threshold, the cal-culation on the number is not that accurate already. The Number.MAX_SAFE_INTEGER is themaximum integer for safe calculation.

1 Number.MAX_SAFE_INTEGER

2 // -> 9007199254740991

3

4 Number.MAX_SAFE_INTEGER + 1

5 // -> 9007199254740992

6

7 Number.MAX_SAFE_INTEGER + 2

8 // -> 9007199254740992

Calculations with fractional numbers can also produce imprecise result either.

Page 13: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Types 8

1 0.001 - 0.0003

2 // -> 0.0007000000000000001

Hence, keep in mind that fractional digital numbers should be treated as approximatedresult and not be used in exact equality comparison either. If you want to learn more indetail, you can take a look on the Double-precision floating-point format1.

What happen if we multiply the maximum value by 2? Will there be any error? Stay calm.Experiment on programming language is much safer than physics or chemistry. Let’s tryout the Number.MAX_VALUE * 2 in the Node.js console.

What do you got? Infinity, right? That is a special number in JavaScript. See what youcan get if we use the operators we learned before on it, like Infinity + Infinity, Infinity/ Infinity, Infinity * -1.

Another strange result NaN should be produced if you did try. NaNmeans Not a Number,and 0 / 0 can also produced that. Any numeric operation involved NaN yields the resultof NaN itself. One very special feature on it is that it does not equals to itself. You can tryabout that after you learned the comparison operators later.

2.3 String

Besides numbers in real world, another common type of information we produced istext. String data type is used to represent text in many programming language, so doesJavaScript. Below are two String representative using quotes to enclose the text content.

1 'Ever imagine how easy JavaScript is?'

2 "Tell me about it."

If quotes are used to enclose the text content to represent String, what can I do if thetext I want to show contains quotes? You just need to make sure the quote inside thetext content is different than the ones used to enclose it. In case you do have to use thesame style of quote, you need to escape the quote character in text content by usingbackslash (\).

1https://en.wikipedia.org/wiki/Double-precision_floating-point_format

Page 14: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Types 9

1 console.log('I love reading "Tasting JavaScript".');

2 // -> I love reading "Tasting JavaScript".

3

4 console.log("It's fantastic");

5 // -> It's fantastic

6

7 console.log('It\'s fantastic');

8 // -> It's fantastic

Notes: The console.log() is a JavaScript function. Function concept will be introducedlater. For now, you just need to know that it helps to print out the thing you put insideits parentheses.

Besides escaping, backslash actually have the capability of empowering the characterright after it has special meaning. For example, if you want to separate your text contentinto multiple lines, you can use \n (new line character) inbetween.

1 console.log('It\'s fantastic.\nCome and learn JavaScript.');

2 // -> It's fantastic.

3 // -> Come and learn JavaScript.

I will leave a question here: How to print out the backslash itself?

Actually, if the environment you play around complies with ES6, ECMAScript 6 standard,there is one more convenient way to represent multiple lines’ text. You can use a pair ofback-tick to enclose the multi-line strings.

1 console.log(`

2 Free-style writing here.

3

4 Without any constraints.

5 Feels great!

6 `);

Is that we can just print out the String?What else canwe do about it? Themost commonlyseen String operation is to use the + operator to concatenate them. Why go through thetrouble of concatenation while we can simply write a full sentence? Because after welearn about variable and function later, we might need to dynamically glue the thingstogether. At that time, this would be very useful.

Page 15: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Types 10

1 console.log('It' + '\'s' + ' ' + 'combined' + ' together.');

2 // -> It's combined together.

2.4 undefined & null

In JavaScript, two values both represent the absence of a value, but belong to twodifferent data types. undefined is undefined data type while null is object data type. This isactually a design flaw in JavaScript. Most of the time, they are interchangable. However,I would suggest that you should use them following some good practices which I willshow you in chapters about Object and Function.

2.5 Boolean

Boolean data type has just two value of Boolean, true and false. They are seldom usedvisually like the number and string type. Decisionmaking in program flow control is theirmajor usage and it will be introduced in next chapter. Normally, the Boolean value isyielded from comparison operators, <, >, <=, >=, ==, ===, != and !==.

1 1 == 1

2 // -> true

3

4 2 != 2

5 // -> false

6

7 10 > 9

8 // -> true

9

10 8 < 6

11 // -> false

12

13 'hello' < 'hi'

14 // -> true

15

16 'Hello' < 'hello'

17 // -> true

18

19 'Hello' < 'ä½ å¥½'

20 // -> true

Comparing String value might seems unnecessary at first. However, it’s useful whenyou want to sort some text, sentences for example. When comparing String, uppercase

Page 16: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Types 11

character is smaller than lowercase; english character is smaller than non-Englishcharacter. The actual mechanism behind is that each character is virtually assigned anumber based on Unicode standard. And JavaScript compares each character in Stringone by one from left to right using that numberic code behind.

2.6 Automatic Type Coersion

The operators we introduced normally require value of same data type in order to havemeaningful result. However, it will not generate any error but produce some strangeresult sometimes if you feed different types of value to it. JavaScript does somethingcalled Automatic Type Coersion behind based on some complex rule.

1 1 > 'a' // The 'a' is converted to number type which is NaN here

2 // -> false

3

4 1 < 'a'

5 // -> false

6

7 1 == true

8 // -> true

9

10 0 == false

11 // -> true

12

13 '' != false

14 // -> false

15

16 '5' + 1

17 // -> '51'

18

19 '5' - 1

20 // -> 4

21

22 undefined == null

23 // -> true

24

25 1 * null

26 // -> 0

27

28 1 * undefined

29 // -> NaN

Page 17: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Types 12

30

31 !''

32 // -> true

It’s really not easy to remember all the rules. Hence, we should avoid any operationinvolved different types of value. That is why two strict equality comparison operators=== and !== are provided to enforce comparing data type as well.

1 undefined === null

2 // -> false

3

4 0 === false

5 // -> false

2.7 Conditional & Logical Operators

Conditional operator, also the only tenary operator, consists of a question mark and acolon.

1 true ? 'left' : 'right'

2 // -> 'left'

3

4 false ? 'left' : 'right'

5 // -> 'right'

The expression on the left of the question mark is the condition to evaluate. The valueon the left of the colon mark is picked when the condition is true; the value on the rightis picked when the condition is false.

Logical operators &&, ||, ! (exclamation mark) represents the logical AND, OR and NOTrespectively.

1 !true

2 // -> false

3

4 true && false

5 // -> false

6

7 false || true

8 // -> true

Actually, it’s not necessary to use boolean type value in && and ||. What is more, thereturn value of the expression is not the final boolean result but the left side or rightside value. Let’s see some example before explanation.

Page 18: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Types 13

1 // --- && scenarios --- //

2

3 1 < 2 && 2 // When left side expression is true, return right side value

4 // -> 2

5

6 1 > 2 && 2 // When left side expression is false, return left side value

7 // false

8

9 1 && 2 // Converts 1 to true, return right side value

10 // -> 2

11

12 0 && 2 // Converts 0 to false, return left side value

13 // -> 0

14

15 // --- || scenarios --- //

16

17 1 < 2 || 0 // When left side expression is true, return left side value

18 // -> true

19

20 1 > 2 || 0 // When left side expression is false, return right side value

21 // -> 0

22

23 1 || 2 // Converts 1 to true, return left side value

24 // -> 1

25

26 0 || 2 // converts 0 to false, return right side value

27 // -> 2

Why is that? It seems confusing at the beginning and difficult to memorize it. But it willbe clear after you know the mechanism behind, the Short-circuit evaluation.

You know, if && logically represents AND, that means the whole && expression can be true

only when both side of the expression is true. Hence, if the left side is false, then theright side expression is not necessary to be evaluated and so it returns value of the leftside expression immediately. If the left side is true, the right side value determines thevalue of the whole expression and so it returns the right side expression.

For the same reason, if || locally represents OR, that means the whole || expressioncan be true when either side of the value is true. Hence, if the left side is true, then theright side value is not necessary to be evaluated and so it returns value of the left sideexpression immediately. If the left side is false, the right side value determines the valueof the whole expression and so it returns the right side expression.

The Short-circuit evaluation allows us to put more complex evaluation to the right-handside for better performance by reducing unnecessary operation. And another commonly

Page 19: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Types 14

use case to take advantage of Short-circuit evaluation is to fall back on a default value.Below example seems silly but this concept is useful when it’s used in variable declarationor function parameter.

1 console.log(null || 'default name');

2 // -> 'default name'

3

4 console.log('Ken' || 'default name');

5 // -> 'Ken'

Page 20: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

3. Program Structure and FlowControlAny fool can write code that a computer can understand. Good programmerswrite code that humans can understand.– Martin Fowler

What we have learned in the previous chapters cannot be really called programming yet.A finished program is like an article. The main purpose of writing a program is to let thecomputer to do some work for you, but also it’s more important to concisely and clearlyexpress your idea.

3.1 Expressions & Statements

A program is formed by a series of statements just like an article is formed by sentences.What we have learned so far is just the building block, expressions, of statements. To bemore precise, an expression is a fragment of code that produces value. Simple value isthe most basic unit of expression. You can combine many simple expressions to form amore complex expression just like composing phrases together. Below are some samplesof expressions.

1 'me'

2 // -> 'me'

3

4 1 + 1

5 // -> true

6

7 'you' && 'me'

8 // -> 'me'

As writing program is actually instructing what the computer should do, each statementshould be a complete instruction, although that is not mandantory just like you cansimply use only an exclam as a sentence. The completeness in JavaScript is normallyindicated by an ending ; character. Below are samples of statements.

Page 21: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 16

1 'aha'; // Not useful but still a statement

2

3 console.log('Show me the code.'); // This instructs computer to print out some t\

4 ext

Notes: the ; is not necessary to annotate the end of a statement. Simply pressing Enter

and form a newlie will do. JavaScript execution environment is intelligent enough todetect whether it’s a complete statement.

3.2 Variables

Looked back to the expressions or statements we wroted before, we use the valueimmediately and cannot refer it back later. If we want to build a program to keep track ofour bank account, wemust refer to it from time to time in order to do deposit, withdrawalor balance checking, right? Variable is what we use in almost every programminglanguage for this purpose.

In JavaScript, the var keyword is used to define a variable andwe can assign a value to thevariable by using a = followed by the value. We can simulate an bank account operationswith below statements.

1 var myBankAccountBalance = 100; // Account opened with 100 do\

2 llar

3 myBankAccountBalance = myBankAccountBalance + 200; // Deposit 200 dollar

4 myBankAccountBalance = myBankAccountBalance - 50; // Withdraw 50 dollar

5 console.log(myBankAccountBalance); // Check account balance

6 // -> 250

Besides var, keyword const and let also allow you to define variables. Both of these twokeywords are newly supported in ES6 standard. letwill be introducedwhenwe talk aboutFunction and scope later. For const, it’s used for the case you don’t want your variable tobe changed to point to another value after it’s first assigned.

Notes: keyword const and let are introduced in ES6. In order to use it, you need to putthe String 'use strict' in the first line of the JS file. In the future, please put this Stringin all of your JS files.

Page 22: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 17

1 const notChangable = 1;

2 notChangable = 2;

3 console.log(notChangable);

4 // -> 1

Convention

There are some rules need to be followed when we choose a variable name:

1. Cannot use the reserved words, such as var.2. Cannot contain spaces.3. Cannot start with number, like 123abc.4. Cannot contain punctuation except characters $ or _.5. It’s case sensitive.

Notes: The full list of keywords and reserved words below are pretty long, and you donotneed tomemorize all of them at once. You will learnmost of them through out this book.

break case catch class const continue debugger default delete do else enumexport extends false finally for function if implements import in instanceofinterface let new null package private protected public return static superswitch this throw true try typeof var void while with yield

Some general conventions are formed for naming variables through out the years ofprogramming history. Two commonly used in naming variables are as below.

1. Use camelCase1 or snake_case2 consistently in your program.2. Constants normally use capital letters, such as PI.

Actually, many companies have formed a complete style guides on different aspectsin JavaScript beside naming variables, such as Google3, Mozilla4, Airbnb5, etc. To be aqualified programmer, writing code with good style is a must. If you are just learning byyourself now, you can simply pick one above and refer to corresponding sections whenyou learn different chapters in this book. If you are in company already, you may askfrom senior staffs for your company’s version.

1https://en.wikipedia.org/wiki/CamelCase2https://en.wikipedia.org/wiki/Snake_case3https://google.github.io/styleguide/javascriptguide.xml4https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/Coding_Style5https://github.com/airbnb/javascript

Page 23: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 18

Refer, not contain

The relationship between the variable and the value behind it can be imagine as the keyto a box. It’s NOT that the variable contains the value in it. A variable can be reassignedto another value, like a key can be reformed for another box. But the consequence of itis that the original value (box) might have no variable (key) to point to. The value in thebox, when no variable pointing to, would be recycled so that your computer’s memorycan be freed up for other usage. This is called Garbage Collection and it is automaticallydone. Another scenario is that we can produce multiple keys to point to the same box.

1 var color = 'Blue';

2 console.log(color);

3 // -> Blue

4

5 color = 'Green'; // Now the box with value 'Blue' has no key pointing to it.

6 console.log(color); // It's NOT that the box with 'Blue' value is replaced by 'G\

7 reen'

8 // -> Green

9

10 var colour = color; // Now there is one more key pointing to box with value 'Gre\

11 en'.

12 console.log(colour)

13 // -> Green

Let’s see one more example:

1 var a = 100

2 var b = a

3

4 a -= 50

5

6 console.log(a) // -> 50

7 console.log(b) // -> 100

Default value

When we define a variable but not assign a value right away, the key points to no box.Now if you check the value of the variable, it tells you undefined.

Page 24: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 19

1 var nameOfNewBornBaby;

2 console.log(nameOfNewBornBaby);

3 // -> undefined

Dynamic nature

In JavaScript, you can freely assign any value to a variable. The key can first point to aString type value. And then you can reassign it to point to a Number or Boolean typevalue and there is no error or warning about it. This is because JavaScript is a dynamicprogramming language6. However, it’s NOT a good practice to change a variable to pointto different value. And we should name our variable better to help you infer its usageand data type.

When you need to check a data type of the value one variable points to, you can usetypeof operator. It returns a String value indicating what type it is so that you can usecomparison operators === or !== to perform your logic accordingly based on appropriatedata type.

1 var whoAmI;

2 console.log(typeof whoAmI);

3 // -> undefined

3.3 Run program file in Node.js

After we learn control flow, wewill write longer andmore complex program havingmanystatements. It is not convenient to directly type statements in Node.js console anymore.Actually, you can provide a file containing all the statements for Node.js to execute. Thereare just two steps required:

1. Put all your JavaScript statements in a file with .js suffix, such as program.js2. Execute command node program.js in the command line from the path where the

file is located.

Sample program.js file can contain just one line as below:

1 console.log('Program in file is executed');

6https://en.wikipedia.org/wiki/Dynamic_programming_language

Page 25: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 20

Node.js Execute JS File

3.4 Debug program file in Node.js

Notes: This section should not be difficult if you can get the node-inspector installedsuccessfully. And this section will not affect your JavaScript learning if you skip it. Youcan simply use console.log to print out anything anywhere to debug as well.

As the program grows, we often need to debug the program which means we canexamine the statements to be executed one by one and check what value is assignedto each variable during execution. Unbelievable? There are just three steps required tolearn this time-frozen magic.

1. Install Google Chrome7 browser2. Type command npm install node-inspector -g in command line and press Enter

(Not in the Node.js console).3. Type command node-debug program.js in the command line and press Enter.

Before try it out, let’s change the above program.js to be less silly as below. This programexpects you to pass a name into it so that it can print out a complete salut message. Theprocess.argv helps you to get everything you input in command line when running theprogram with Node.js. Just memorize this usage first.

1 // Leave an empty line at the beginning of the file to display better in debugger

2 var helloMessage = 'Hello, ';

3 var args = process.argv;

4 console.log(helloMessage + args[2]);

After typing in the command as below screencap, you will see the Chrome launches withyour JS file highlighted on first line. Also, you can find that there is a “Scope Variables”sectionwhich shows the “Local” variables there. The two variables helloMessage and argsare both undefined as the program is not run yet. The two buttons highlighted with redrectangle are what we need to pay attention now. The left one is to run the program fromcurrent highlighted line until it reaches a breakpoint, which is a pause signal; the rightone is to run current highlighted statement only and then pause on next statement.

7https://www.google.com/chrome/browser/desktop/index.html

Page 26: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 21

Node.js Debug Start

If you use your mouse to click on the line number 4, it creates a breakpoint there. Allthe breakpoints are shown in the “Breakpoint” section where I highlighted with bluerectangle.

Node.js Debug Breakpoint

Now if you click the button on the left mentioned above, the execution will stop at thebreakpoint. At this moment, you can see that the value of helloMessage and args areassigned with actual value.

Page 27: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 22

Node.js Debug Step

When you click the button on the right mentioned above, it runs the highlightedstatement only. You can find out the message is printed out in the Chrome console.

Page 28: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 23

Node.js Debug End

3.5 Control Flow

When reading an article, we normally read from top to bottom, sentence after sentencesequentially. Similarly, that is also the basic flow that statements are executed inside aprogram. But more diverse ways are supported in programming so that we can instructthe computer to do more complex tasks.

Conditional - if

The if keyword allows us to control some statements to be executed under particularconditions only. For example, we want our program to verify the digit passed fromcommand line is even number (multiple of 2) or not. If it is, it prints out a message.We can write the program as below. Then if we run the program as node program.js 2, itprints out the message.

Page 29: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 24

1 var args = process.argv;

2 var digit = Number(args[2]); // Converts the input parameter to number

3

4 if (digit % 2 === 0) {

5 console.log('Digit ' + digit + ' is even number.');

6 }

Notes: The curly braces {} is used to enclose statements to form a code block. We canput multiple statements inside it. The {} is not necessary here because there is just onestatement to be executed. However, it’s considered to be good practice for consistencyand avoid introducing bug when adding/removing statements in the future.

When our input digit is not an even number, the program does nothing. Would it bemoreuser-friendly to print something else to let user knows what happened? else keywordallow us to specify the otherwise execution path when the if condition is not met.

1 var args = process.argv;

2 var digit = Number(args[2]);

3

4 if (digit % 2 === 0) {

5 console.log('Digit ' + digit + ' is even number.');

6 } else {

7 console.log('Digit ' + digit + ' is odd number.');

8 }

Actually, amulti-path execution flow can be built by combining unlimited number of elseif into it.

1 var args = process.argv;

2 var digit = Number(args[2]);

3

4 if (digit % 5 === 0) {

5 console.log('Digit ' + digit + ' is multiple of 5.');

6 } else if (digit % 3 === 0) {

7 console.log('Digit ' + digit + ' is multiple of 3.');

8 } else if (digit % 2 === 0) {

9 console.log('Digit ' + digit + ' is multiple of 2.');

10 } else {

11 console.log('Digit ' + digit + ' is confusing me.')

12 }

Page 30: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 25

Conditional - switch

JavaScript provides another keyword switch for conditional flow that supports multipleexecution path. We can use the switch keyword to simulate the above even and oddnumber example as below, plus fixing a bug when you don’t provide a digit.

1 var args = process.argv;

2 var digit = Number(args[2]);

3

4 switch (digit % 2) {

5 case 0:

6 console.log('Digit ' + digit + ' is even number.');

7 break;

8 case 1:

9 console.log('Digit ' + digit + ' is odd number.');

10 break;

11 default:

12 console.log('What did you gave me to reach here?');

13 break;

14 }

15

16 console.log('Tough decision is made.');

switch evaluate the value of the expression digit % 2. Each value followed the case

keyword is used to strictly compare (using ===) with the expression value. If there isno case matched, the statements under default clause are executed. When the break

keyword is met, the execution breaks out of the switch and continues the statementafter it (“Tough decision is made.” will be printed).

Some key points to be noted:

1. If there are multiple cases matched, which we shouldn’t do, the statements belowthe first case matched will be executed.

2. If the break statement is omitted, fall-through happens. That means the programwill not stop and continue to execute the statements under other cases. We shouldtry to avoid this usage which easily causes bug.

3. default clause is optional and by convention is the last clause but it does not needto be.

4. Considering efficiency, frequently met case should be arranged at the beginning.

Page 31: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 26

Loop - while

Reducing repeated tasks is an advantage of computer and one of the basic feature inalmost every programming language. Not like workout, repeating task doesn’t meandoing exactly the same thing many times. For example, if we want to know the sum ofthe number from 1 to 100, doing addition on different digits is also a form of repeatedtasks.

Loop in programming language is used to address this issue. Without it, writing programas below makes no difference than using a calculator. But for the god’s sake, how muchtime and space it needs to take?

1 1 + 2 + 3 + 4 + 5 + ... // Where would be the end?

JavaScript provides a while keyword to indicate the code block for loop. Below statementscan achieve the same purpose above with greater brevity.

1 var sum = 0;

2 var currentNumber = 1;

3 while (currentNumber <= 100) {

4 sum = sum + currentNumber;

5 currentNumber = currentNumber + 1;

6 }

7 console.log(sum);

8 // -> 5050

It is not that difficult to understand if you take it like reading an article: While current-

Number is smaller or equal to 100, plus it to the sum and plus 1 to currentNumber. WhencurrentNumber does not meet above condition anymore, loop stops and the programprints out the sum.

Let’s make slight change in order to have greater brevity.

1 var sum = 0, currentNumber = 1;

2 while (currentNumber <= 100) {

3 sum += currentNumber;

4 currentNumber += 1;

5 }

6 console.log(sum);

1. Using var to declare variables can be combined into one line using a comma.

Page 32: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 27

2. sum = sum + currentNumber can be replaced to sum += currentNumber and similarlycurrentNumber = currentNumber + 1 can be replaced with currentNumber += 1. It’snot easy to understand at the beginning. For this kind of self modification, theoperation and assignment can be combined with such short form. This rule appliesto *, -, /, % as well. If the variable self increase or decrease one, there is anothermore concise form, ++ and --.

1 var sum = 0, currentNumber = 1;

2 while (currentNumber <= 100) {

3 sum += currentNumber;

4 currentNumber++;

5 }

6 console.log(sum);

You may not know, the ++ and -- can even be placed before the variable. But its behaviorhas a little bit difference. Please check below two samples which produce the same resultand find out the minor difference.

1 var sum = 0, currentNumber = 1;

2 while (currentNumber <= 100) {

3 sum += currentNumber++;

4 }

5 console.log(sum);

6

7 var sum = 0, currentNumber = 0; // Initial value need to be 0.

8 while (currentNumber < 100) { // currentNumber cannot be equal to 100 here.

9 sum += ++currentNumber;

10 }

11 console.log(sum);

When the ++ is placed after the variable, the behavior is normal. It means the value ofthe variable, currentNumber here, is used in the outer statement, sum += currentNumber

first and after that, the currentNumber self-increase one. But if the ++ is placed before thevariable, the behavior changes. It means the currentNumber self-increase one first, andthen its value is used in the outer statement.

I am not intent to twist your mind here. You don’t need to force yourself to understandthe different usage of ++ at this moment. You just have to keep in mind that when yousee it, be careful. After written the code in above form, although it’s shorter, it’s not thateasy to understand any more. The intention here is to let you know that purely pursuingshorter code using some fancy language feature is not true brevity.

while loop actually still have one more form, do ... while. If some task has to be doneat least once, you can use this style.

Page 33: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 28

1 var sum = 0, currentNumber = 1;

2

3 do {

4 sum += currentNumber;

5 currentNumber++;

6 } while (currentNumber <= 100);

7

8 console.log(sum);

Loop - for

for is another keyword can be used to express a loop statement. Please see belowrewritten sample.

1 var sum = 0;

2 for (var currentNumber = 1; currentNumber <= 100; currentNumber++) {

3 sum += currentNumber;

4 }

5 console.log(sum);

There are three statements inside the parentheses ():

1. The leftmost one is called initialization. Actually you can put the sum = 0 part thereas well, such as var sum = 0, currentNumber = 1. It’s evaluated once.

2. The middle one is called condition. It’s evaluated before each loop iteration. If theexpression is evaluated to false, the code block inside will not be executed.

3. The rightmost one is called final-expression. It’s evaluated at the end of each loopiteration, before the next evaluation of condition. Hence, it’s generally used toupdate the variable used in condition.

The above three parts are not mandatory and you can put the initialization before for,such as in the same line of initializing variable sum. And you can put the condition andfinal-expression part inside the {}. But if you do so, does it just like a while loop? Thesethree parts are common pattern in a loop. The major advantage of for loop over whileloop is that it groups all state control statements at the beginning for brevity.

Loop Interruption - break

Sometimes, we want to stop the loop before the loop’s condition in for and while to beevaluated as false. This is very useful when we are inspecting a bunch of things and wantto skip the rest after we find out the one we need.

Below is the rewritten sample of the above while and for loop sample on calculating sum.

Page 34: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 29

1 // Rewritten while sample

2 var sum = 0, currentNumber = 1;

3 while (true) {

4 sum += currentNumber;

5 currentNumber++;

6

7 if (currentNumber > 100) {

8 break;

9 }

10 }

11 console.log(sum);

12

13

14 // Rewritten for sample

15 var sum = 0;

16 for (var currentNumber = 1; ; currentNumber++) {

17 if (currentNumber > 100) {

18 break;

19 }

20 sum += currentNumber;

21 }

22 console.log(sum);

Loop Interruption - continue

There are scenarios that we just need to skip some iteration inside a loop but notbreaking out the whole loop like above. For example, I just want to print out the evennumber from 1 to 100. The program can be written as below.

1 var currentNumber = 0;

2 while (currentNumber <= 10) {

3 if (currentNumber % 2 == 0) {

4 console.log(currentNumber);

5 }

6

7 currentNumber++;

8 }

9

10 for (var currentNumber = 0; currentNumber <= 10; currentNumber++) {

11 if (currentNumber % 2 == 0) {

12 console.log(currentNumber);

13 }

14 }

Page 35: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 30

But we can also use a continue statement to explicitly skip a particular loop iteration.

1 var currentNumber = -1;

2 while (currentNumber <= 10) {

3 currentNumber++;

4 if (currentNumber % 2 == 1) {

5 continue;

6 }

7

8 console.log(currentNumber);

9 }

10

11 for (var currentNumber = 0; currentNumber <= 10; currentNumber++) {

12 if (currentNumber % 2 == 1) {

13 continue;

14 }

15

16 console.log(currentNumber);

17 }

So, when should we choose continue to explicitly skip an iteration against judging theopposite condition and enclose the statements to execute? It might be just a matter oftaste or depend on how many statements actually need to execute under the condition.If there aremany statements instead of just an console.log, the code can bemore brevityif you use continue in the beginning of the loop so that you don’t need to placemany linesof statements inside the curly braces and indent too many levels.

However, make sure the continue statement don’t skip the statements that changethe condition. Else, the loop can be turned into an infinite loop. For example, thecurrentNumber++; in above while loop cannot be placed at the end of the code block.

3.6 Comments

I have mentioned previously that words after two slashes // are a comment and it doesnot affect program running result. That usage is for a one-liner comment. If we need towrite multiple sentences with line break in comments, we can put those words between/* and */.

Page 36: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 31

1 /*

2 My birthday is 21st Jun.

3

4 That is why I decided to set the price of this book to be

5 maximum 6.21 and minimum 1.26 dollar.

6 */

7 var originOfPrice = 621;

3.7 Exercises

Triangle

Please write a program to accept a numeric parameter from command line and print outa triangle. Below is an example of triangle when input parameter is 5:

1 #

2 ##

3 ###

4 ####

5 #####

Hints: process.argv, console.log, Loop, String concatenation

Holed triangle

Below is also an example of triangle with input parameter of 5. Your task is still acceptinga number from command line and print out the triangle accordingly.

1 #

2 # #

3 # # #

4 # # # #

5 # # # # #

Hints: process.argv, console.log, Loop, if, String concatenation

Page 37: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Program Structure and Flow Control 32

Bing! Go! Bingo! Boom!

Write a program to accept a numeric parameter from command line. Make a loop from1 to 100. Check each number and see if it’s divisible by the parameter. If it’s, print out thenumber followed by “: Bing!”. Check each number and see if it’s divisible by the numberwhich equals to the parameter plus 1. If it’s, print out the number followed by “: Go!”.If the number fulfill both rules above, print out the number first, and then followed by“: Bingo!”. If the number is divisible by (parameter * (parameter + 1) * (parameter + 2)),print out the number and followed by “: Boom!” and break out of the loop. Below is theexample if you input 2 as parameter.

1 2: Bing!

2 3: Go!

3 4: Bing!

4 6: Bingo!

5 ...

6 24: Boom!

Hints: process.argv, console.log, Loop, if, String concatenation, break

Page 38: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

4. FunctionIt is better to have 100 functions operate on one data structure than 10functions on 10 data structures.– Alan J. Perlis

As wementioned before, function is also one kind of data type in JavaScript. It representsa piece of executable code which includes some statements. But why do we need to wrapsome statements into a function?

For example, if we want to calculate the absolute value of provided numbers fromcommand line, we might write some code similar as below:

1 var args = process.argv;

2

3 console.log(args[2] >= 0 ? args[2] : -args[2]);

4 console.log(args[3] >= 0 ? args[3] : -args[3]);

5 console.log(args[4] >= 0 ? args[4] : -args[4]);

6 ...

What are the problems here? What can be improved?

1. Repetition As you can see, the expression args[2] >= 0 ? args[2] : -args[2] re-peats several times and the difference is just the variable used in it. Oncewewant tochange the way we calculate absolute value, we have to change all the occurences.

2. Readability Even though the single expression args[2] >= 0 ? args[2] : -args[2]

is quite simple already, it’s still not obvious at first glance. What if we can give it aname, like getAbsoluteValue? Would it be more readable?

Function is a very important concept, Abstraction, in every programming language. Ithides the implementation detail and allows us to use more expressive vocabularies topresent what a program intends to accomplish.

It’s a very good practice to write clear and concise functions, and compose them togetherto accomplish a great thing instead of writing a single large one. Some companies mighteven have a hard rule to enforce the max length of a function, such as 20 lines.

Let’s see how it looks like and why it’s indispensable in every programming language.

Page 39: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 34

4.1 Definition

Expression

The first approach to define a Function is like declaring a variable and called function

expression. The above program can be revised as below if we define a getAbosoluteValue

function.

1 var getAbsoluteValue = function(value) {

2 return value >= 0 ? value : -value;

3 }

4

5 var args = process.argv;

6

7 console.log(getAbsoluteValue(args[2]));

8 console.log(getAbsoluteValue(args[3]));

9 console.log(getAbsoluteValue(args[4]));

10 ...

Function is defined by using a function keyword and () and {} followed.

1. Zero to many parameters are wrapped inside the (). The function getAbsoluteValue

above just have one parameter named value. If you imagine the function as anoven, parameters are the raw materials you put inside it.

2. All the statements wrapped inside the {} is function body. The {} is mandatory evenif you have only one statement as above.

3. Optional return statement can be included in function body. The function getAb-

soluteValue returns the absolute value of the number. But we can also put theconsole.log inside the function so that there is no return statement in it. But in thiscase, the function actually return an undefined value. When the program executioncome to the return statement, the rest of the statements, if there is any, in thefunction body will be ignored.

Notes: The getAbsoluteValue is renamed to printAbsoluteValue to better represent whatit really does.

Page 40: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 35

1 var printAbsoluteValue = function(value) {

2 console.log(value >= 0 ? value : -value);

3 }

4

5 var args = process.argv;

6

7 printAbsoluteValue(args[2]);

8 printAbsoluteValue(args[3]);

9 printAbsoluteValue(args[4]);

10 ...

For this style of function definition, the function is like other normal variables. You canassign it to another variablewith different names (multiple keys pointing to the samebox,remember?); print it out; pass it to another function, and so on. In Chapter 6, when wetalk about Functional Programming and Higher Order function, you will see how amazingon passing function as value.

Declaration

Another approach to define a function is called function declaration. Its syntax is similarto expression but you put the name after the function keyword and no need to assign itto another variable. Above example can be revised as below.

1 function printAbsoluteValue(value) {

2 console.log(value >= 0 ? value : -value);

3 }

4

5 var args = process.argv;

6

7 printAbsoluteValue(args[2]);

8 printAbsoluteValue(args[3]);

9 printAbsoluteValue(args[4]);

10 ...

The syntax is a little bit shorter than the first one, but the dramatic difference is as below.

Page 41: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 36

1 var args = process.argv;

2

3 printAbsoluteValue(args[2]);

4

5 function printAbsoluteValue(value) {

6 console.log(value >= 0 ? value : -value);

7 }

8 ...

You see, the function can be called even before it’s declared. This is called Hoisting. Wewill talk about it more when introducing the scope concept later in this chapter.

4.2 Parameters

Optional Parameters

As I mentioned in last chapter, JavaScript is a dynamic programming language. Here isanother dynamic area that when you call a function. You are not necessary to pass asmany as parameters as it’s defined in it. For example:

1 function magicLabor(normalPay, tips) {

2 var labor = normalPay;

3 var magicPower = tips || 0

4

5 return labor + magicPower * 2

6 }

7

8 magicLabor(10, 5) // -> 20

9 magicLabor(20) // -> 20

If you place some optional parameters at the end of the parameter list, you can treatthat value as the customization part of your function. When you call the function withoutspecifying that parameter, the program can use a pre-defined value within the function.

Of course, you can pass more parameters to the function as it’s defined. It has no harmbut just looks a little silly if those parameters are not intended to be used in the function.

Arguments Object

Actually, there exists one very special way to get all the parameters passed to a functioneven though you define NO parameters in the function signature. This is a very powerfulbullet. It’s the arguments object. It is only availabe within the function, and you can inspectits content like below.

Page 42: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 37

1 function whatWasThrownToMe() {

2 for (var i = 0; i < arguments.length; i++) {

3 console.log(arguments[i])

4 }

5 }

6

7 whatWasThrownToMe(1)

8 // -> 1

9

10 whatWasThrownToMe('A', 'B')

11 // -> A

12 // -> B

Parameters are keys, not boxes

The value of the parameters are passed from the outside world to the function. Butremember, parameters are just variable. The parameters you refer within the functionare just another copies of the keys, not the boxes containing the value. That meanswhen you reassign another value to the parameter, it DOES NOT change the outervariable. Let’s see below example:

1 var bankAccountBalance = 100

2

3 function stealMoney(balance) {

4 balance -= 50

5 }

6

7 console.log(bankAccountBalance)

8 // -> 100

4.3 Scopes

Scope is the concept regarding the visibility of the variables. Let’s start the explanationwith below example.

Page 43: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 38

1 // Usage of 'use strict':

2 // 1. Allows the usage of `let`

3 // 2. Forbid using variable `powerLeaking` before declaring it.

4

5 'use strict'

6

7 var sunLightPower = 100;

8

9 function electricPaybackFromMyHouse(outerElectric) {

10 var normalConsumption = 80;

11 var fuelElectricGenerator = 50;

12 var sunlightElectricGenerator = sunLightPower / 4;

13

14 console.log('Checking diff: ' + diff); // -> Checking diff: undefined

15

16 function addKidsPowerConsumption() {

17 var kidsCount = 3;

18

19 for (let i = 1; i <= kidsCount; i++) {

20 normalConsumption += 10;

21 }

22 console.log('Checking i out of for loop: ' + typeof i);

23 // -> Checking i out of for loop: undefined

24 }

25

26 addKidsPowerConsumption();

27 console.log('Checking kidsCount out of function: ' + typeof kidsCount);

28 // -> Checking kidsCount out of function: undefined

29

30 var diff = fuelElectricGenerator + sunlightElectricGenerator

31 - normalConsumption; // Code wrapping here is acceptable

32

33 if (outerElectric) {

34 diff = outerElectric + normalConsumption;

35 }

36

37 // powerLeaking = 10;

38

39 return diff > 0 ? diff : 0;

40 }

41

42 var paybackPower = electricPaybackFromMyHouse(80);

Page 44: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 39

43

44 // console.log(powerLeaking); // -> 10

45 console.log('Checking normalConsumption out of function: ' + typeof normalConsum\

46 ption);

47 // Checking normalConsumption out of function: undefined

48 console.log('Checking addKidsPowerConsumption out of function: ' + typeof addKid\

49 sPowerConsumption);

50 // Checking addKidsPowerConsumption out of function: undefined

OK, don’t be panic after seeing such a long function. Follow my explanation steps belowto check one by one. Imagine above code is in a JavaScript file that executed by node.

1. sunLightPower is in the outermost, global, scope. It can be seen within the functionelectricPaybackFromMyHouse.

2. normalConsumption is within the local scope of function electricPaybackFromMyHouse

and can be seen within function addKidsPowerConsumption.3. Similarly, kidsCount is only within the local scope of function addKidsPowerCon-

sumption and addKidsPowerConsumption is only within the local scope of functionelectricPaybackFromMyHouse.

4. i is declared using let. It is new in ES6 and allow us to define a block scope variable.Hence, it’s not available outside of the for statement. But if you switch the let tovar, you can print out the value of i.

5. The commented powerLeaking related statements can be uncommented if youremove 'use strict' statements and the addKidsPowerConsumption part. The pointI want to illustrate is that when we declare a variable but accidently miss the var

keyword, the variable becomes global scope. This is dangerous because it pollutesthe outer environment and might cause unexpected bug.

6. Why diff can be directly used instead of using typeof to check about? Rememberthe Hoistingmentioned before? The function or variables declared will be lifted upto the beginning of the scope (locally within a function or globally) it belongs to.

This is called lexical scoping in JavaScript. The scope of the variable is determined by itslocation in source code and so it’s lexical. In short, the nested functions can refer to theouter scope enclosing it. The outer scope cannot see the inner scope.

4.4 Recursion

By definition in Wiki1:

1https://en.wikipedia.org/wiki/Recursion_

Page 45: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 40

Recursion in computer science is a method where the solution to a problemdepends on solutions to smaller instances of the same problem

It is a little bit abstract at first glance. Let’s learn about it through an example. Supposedyou are required to calculate the multiple of the whole number from 1 to 10, that is 1 +

2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10. Of course we can write a loop to do that like:

1 function additionOfWholeNumbersUpTo(max) {

2 var sum = 1;

3

4 for (var i = 1; i <= max; i++) {

5 sum += i;

6 }

7

8 return sum;

9 }

10

11 console.log(additionOfWholeNumbersUpTo(10))

12 // -> 55

How to break this problem down to smaller intances of the same problem? First, we canrevise the expression into this format:

((((((((((1) + 2) + 3) + 4) + 5) + 6) + 7) + 8) + 9) + 10)

I know this forat is even harder to understand at first glance, but actually it should helpsyou see the pattern more clearly. Speaking in human lanuage, this expression meansthat the additionOfWholeNumbersUpTo(10) actually equals to 10 + additionOfWholeNumber-

sUpTo(9) and the additionOfWholeNumbersUpTo(9) equals to 9 + additionOfWholeNumber-

sUpTo(8) and so on and on. Hence, the problem can be abstracted as additionOfWholeNum-bersUpTo(n) can be calculated by n + additionOfWholeNumbersUpTo(n - 1). It’s referring toitself recursively with such fixed pattern. Previous looping can be rewritten in the formof recursion as:

1 function additionOfWholeNumbersUpTo(max) {

2 return max === 1 ? max : max + additionOfWholeNumbersUpTo(max - 1)

3 }

4

5 console.log(additionOfWholeNumbersUpTo(10))

6 // -> 55

Recursion is a special form of loop. Most of the case if not all, we can revise a programin loop form into recursive form or vice versa. But to be very careful to specify the exitcondition when using Recursion as it’s less obvious than loop form. If the exit conditionis incorrect, it might turn to endless loop.

Page 46: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 41

4.5 Call Stack

When a pile of objects arranged together by putting one on another, it’s called a stack. InJavaScript, when a function is called, an execution context is created. This is a technicalterm defined in ECMAScript specification. You can simply imagine it’s some space/roomcreated to hold the current context including the executable code, value of variables, etc.

The stack always has at least one execution context at the bottom, it’s the global context.If the program executes to a function, then a new execution context is created for thisfunction and put (pushed) to the top of the stack. Then the currently active context isfor this function. When the function execution is completed, the context for it is taken(popped) out of the stack.

Let’s see how the execution context and the stack behaves when using the recursion tocalculate the Factorial2

1 function factorial(n) {

2 return n === 0 ? 1 : n * factorial(n - 1);

3 }

4

5 // factorial(10)

6 // => 3628800

7 // factorial(32768)

8 // => Uncaught RangeError: Maximum call stack size exceeded

Factorial Stack Change Flow

You can see that if we put a very small number 3 for the function and execute it, the sizeof the stack is four already. That is why if we put a very large number to the function, aJavaScript Error occurs. Basically if you see this error, it means there exists an endlessrecursion.

2https://en.wikipedia.org/wiki/Factorial

Page 47: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 42

4.6 Exercises

Any Sum

Define a function, sum, that accepts any number of number type parameters and returnthe sum of all the numbers.

Hints: arguments, Loop

Directory Printing

This exercise involves some of the knowledge introduced in next chapter. If the samplecode I provided cannot help you solve the problem, you can come back to this exerciseafter learning the next chapter about Object and Array.

Please implement a function to use the data provided here3 and print it out in belowformat. The data provided virtually represents the tree data structure of the directory inoperation system. Using recursion is a common way to traverse it.

1 // Program output

2 - [Root]

3 - [Sub-Dir A]

4 - [Sub-Sub-Dir C]

5 - [Sub-Sub-Sub-Dir D]

6 File D-1

7 File A-1

8 File A-2

9 - [Sub-Dir B]

10 File B-1

11 File Root-1

12 File Root-2

Helper Code:

3https://github.com/kenspirit/tasting-javascript-exercise/blob/master/04-function/directory-printing-fixture.js

Page 48: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Function 43

1 // You can check the type of the object through `xxx.type`

2 if (fileSystemObj.type === 'D') {

3 // Do whatever you need

4 }

5

6 // You can get the childs of the object through `xxx.childs`

7 var childObjs = fileSystemObj.childs

8

9 // Use `xxx.length` and loop to access each child

10 for (var i = 0; i < childObjs.length; i++) {

11 var child = childObjs[i]

12

13 // Do whatever you need, say print the name

14 console.log(child.name)

15 }

Hints: Recursion, Loop, console.log

Page 49: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

5. Data StructureAlgorithms + Data Structures = Programs– book written by Niklaus Wirth

Data Structures are the ways we organize the data together for processing in program.Different structures have different ways of access.

For a stack of heavy boxes, the bottom one is laid down first and the top one is put last.While you have to take the one at the top first and the bottomone last. For a pile of bags ofcandy in auto machine, the first one put into the machine is taken first. These structuresare different although they are both accessed in sequence. Some other structures areaccessed by names or positions, like the books in the shelf.

5.1 Object

Primitive data types number, string, boolean are the fundamental data storage unit inJavaScript. However, they are so simple and limited that it’s difficult for us to purely usethem to represent the real world.

Remember I have ever used a variable to represent a bank acount balance? In reality,a bank acount at least consists two more information: account number and owner. Canwe group these two information together with balance instead of separately creating 3different variables?

Object in JavaScript comes to rescue. This data type helps us to organize related datatogether so that we can pass them around and process as a single unit. We caneven attach object with behaviors which is part of the concept of Object OrientedProgramming.

Properties

Properties are the characteristics of the object. Below object definition can be used tomodel the bank account object with three properties, the account number, owner andbalance.

Page 50: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 45

1 var bankAccount = {

2 accountNumber: '000001',

3 owner: {

4 firstName: 'Ken',

5 lastName: 'Chen'

6 },

7 balance: 621

8 };

9

10 console.log(bankAccount.balance);

That is it. Defining an Object just need a pair of {} and specify zero to many propertiesin it. And the property value is not limited to primitive data type. The owner property isalso an object. When we want to access the property of the Object, we use the objectvariable, followed by a dot and the property name.

Now you know the meaning of arguments.length and console.log we used before. lengthproperty of the arguments object represents the number of arguments passed into thefunction. log is a behavior property of console object which we will talk soon below.

Property name actually is a String value. Quotes must be included if the property namecontains non-alphanumeric characters. But using special characters as property namesis not recommended.

1 var bankAccount = {

2 "#": '000001',

3 "owner": 'Ken Chen'

4 };

Method

Object can also have behaviors. A bank account should allow us to check balance, depositand withdraw. How can we assign behaviors to object then? If the property value of theobject is a function, we call it the method of the object. And the method is the behavior ofthe object.

Page 51: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 46

1 var bankAccount = {

2 accountNumber: '000001',

3 owner: {

4 firstName: 'Ken',

5 lastName: 'Chen'

6 },

7 balance: 621,

8 checkBalance: function() {

9 return this.balance;

10 },

11 deposit: function(amount) {

12 if (amount <= 0) {

13 console.log('Invalid deposit amount');

14 return;

15 }

16

17 this.balance += amount;

18 },

19 withdraw: function(amount) {

20 if (amount <= 0) {

21 console.log('Invalid withdraw amount');

22 return;

23 }

24 if (amount > this.balance) {

25 console.log('Not enough balance.');

26 return;

27 }

28

29 this.balance -= amount;

30 }

31 };

32

33 bankAccount.withdraw(21);

34 console.log(bankAccount.checkBalance());

35 // -> 600

There is a special usage here, this. The this keyword here refers to object itself so thatwe can use it to reference the other object properties in method.

The special this

We have seen the normal usage of this in object method above. However, the behaviorof below code is very confusing for many people and often used as interview question

Page 52: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 47

as well.

1 balance = 100;

2

3 var bankAccount = {

4 balance: 200,

5 checkBalance: function() {

6 return this.balance;

7 }

8 }

9

10 var checkBalance = bankAccount.checkBalance;

11 console.log(checkBalance());

12 // -> 100

13 console.log(bankAccount.checkBalance());

14 // -> 200

Although the checkBalance and bankAccount.checkBalance are pointing at the same func-tion (two keys to the same box), executing the function in different forms actually refersto different objects. The calling on checkBalance() refers to the global object and so itsbalance property is the one defined globally (Note that there is no var in front of it) outsideof the function with value 100. If there is no such variable, it prints out undefined instead.

Actually, we can provide the desired object to a function as the object this point to duringfunction execution.

1 function speak() {

2 console.log(this.sound)

3 }

4

5 var dog = {

6 sound: 'Woof',

7 speak: speak

8 }

9

10 var cat = {

11 sound: 'Meow'

12 }

13

14 dog.speak()

15 // -> 'Woof'

16

17 var catSpeak = speak.bind(cat)

Page 53: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 48

18 catSpeak()

19 // -> 'Meow'

20

21 speak.call(cat)

22 // -> 'Meow'

23

24 speak.apply(cat)

25 // -> 'Meow'

The method bind, call, apply can be used to specify the object to be used as this infunction. bind method returns a new function that it remembers the object to be used.While call and apply must be called immediately on the object. More explanation andusage will be discussed in chapter 6 when we learn functional programming.

Enumerate Properties

What if someone else pass us an object but we don’t know what properties it contain? Isthere anyway we can inspect the properties it have? The for ... in statement can helpus to check.

1 var bankAccount = {

2 accountNumber: '000001',

3 owner: {

4 firstName: 'Ken',

5 lastName: 'Chen'

6 },

7 balance: 621,

8 checkBalance: function() {

9 return this.balance;

10 }

11 };

12

13 for (var key in bankAccount) {

14 console.log('Property name: ' + key);

15 console.log('Property value: ' + bankAccount[key]);

16 }

17

18 // -> Property name: accountNumber

19 // -> Property value: 000001

20 // -> Property name: owner

21 // -> Property value: [object Object]

22 // -> Property name: balance

Page 54: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 49

23 // -> Property value: 621

24 // -> Property name: checkBalance

25 // -> Property value: function () {

26 // -> return this.balance;

27 // -> }

There are two special output value:

1. Object value of property owner is printed as [object Object] instead of a pretty printformat contains all its property.

2. Function value of property checkBalance is printed out the code

Why is that? Actually, when we use console.log to print out a string concatenated withan object (function is a special object), the internal toString() method, owned by everyobject, is called. Its behavior differs among different object types and so the valuesprinted out are different.

Mutability

Whenwe are playing around the primitive data types number, string or boolean, we cannotmutate the value. Reassignment is actually making the variable to point to a new value.Hence, those primitive data type are all immutable. But for object, it’s different.

1 var num = 2;

2

3 var obj = {

4 num: 4

5 };

6 var anotherObj = obj;

7

8 function mutate(num, obj) {

9 num = 8;

10 obj.num = 16;

11

12 obj = {num: 20};

13 }

14

15 mutate(num, obj);

16

17 console.log(num); // -> 2

18 console.log(obj.num); // -> 16

19 console.log(anotherObj.num); // -> 16

Page 55: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 50

Reassignment to a variable with object value {num: 4} to another object {num: 20} doesn’tchange the original object. However, if the reassignment is performed on the propertyof the object, the object is changed. If there is other variables, anotherObj above, pointingto the same object, it also sees the change after modification.

5.2 Array

Object data type is good at grouping different values together if they belongs to a singleunit to better represent a real world object. However, it’s not suitable to represent abatch or collection of the data, such as a sequence of numbers.

To facilitate data processing on sequences of value, JavaScript provides a special datatype, called Array. Let’s see how it’s defined and used.

1 var sequenceOfNumbers = [1, 2, 3, 4, 5, 6];

2

3 console.log(sequenceOfNumbers); // -> [ 1, 2, 3, 4, 5, 6 ]

4 console.log(typeof sequenceOfNumbers); // -> object

5

6 for (var index = 0; index < sequenceOfNumbers.length; index++) {

7 console.log(sequenceOfNumbers[index]);

8 }

Array is defined by [] and we put items into it separated by comma. Actually, we haveseen Array beforewhenwe use process.argv to obtain values passed from command line.The length property indicate how many items in it. The numeric index is the position ofthe value in the array. But the numeric index starts from 0 instead of 1. It is a bit odd ifyou have no experience on other programming languages before.

As Array is also Object, when we use typeof operator to check on an array, it return object

as well. In order to detect whether a variable holds reference to an array, we need to useArray.isArray() to check.

Methods

Array is a widely used and important data type. Hence, there are many useful methodsprovided for Array in JavaScript. Some of them aremutation operations whichmeans thechange is applied on the array itself. While some of them are non-mutation operationswhich means the original array is not updated but the method returns the new value.

Non-Mutation Operations:

• indexOf and lastIndexOf can let you know a particular value’s position in Array.

Page 56: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 51

• concat enables you to merge two Array together.• join concatenates all the items into a String.• slicemakes a shallow copy of the array by specifying a start index and an optionalend index.

1 var numbers = [6, 1, 2, 1];

2

3 console.log(numbers.indexOf(1)) // -> 1

4 console.log(numbers.lastIndexOf(1)) // -> 3

5

6 console.log(numbers.join(',')); // -> 6,1,2,1

7 console.log(numbers); // -> [6, 1, 2, 1]

8

9 console.log(numbers.concat([8, 2])); // -> [6, 1, 2, 1, 8, 2]

10 console.log(numbers); // -> [6, 1, 2, 1]

11

12 console.log(numbers.slice(1, 3)); // -> [1, 2]

Mutation Operations:

• push and pop allows you add a value to the end of the array or take it out.• unshift and shift allows you to add a value to the front of the array or take it out.• splice helps removing items from array.• sort and reverse, as the name suggested, sorts the array or reverse it.

1 var numbers = [6, 2, 1];

2

3 numbers.push(9);

4 console.log(numbers); // -> [6, 2, 1, 9]

5

6 console.log(numbers.pop()); // -> 9

7 console.log(numbers); // -> [6, 2, 1]

8

9 numbers.unshift(8);

10 console.log(numbers); // -> [8, 6, 2, 1]

11

12 console.log(numbers.shift()); // -> 8

13 console.log(numbers); // -> [6, 2, 1]

14

Page 57: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 52

15 numbers.sort();

16 console.log(numbers); // -> [1, 2, 6]

17

18 numbers.reverse();

19 console.log(numbers); // -> [6, 2, 1]

20

21 // Remove 2 items starting from index 1

22 console.log(numbers.splice(1, 2)); // -> [2, 1]

23 console.log(numbers); // -> [6]

5.3 Map

Map is a common data structure in many programming languages. It have differentnames, like Dictionary, or Associative Array. It’s a collection of key value pair. Unlikenormal Array, whose value is retrieved through numeric index, Map value access is bykey. Each key appears only once in Map.

Object as Map

I am not sure if Object immediately pop up on your mind after above description. InJavaScript, Object is widely used as a Map with the property as the key. When we useObject as Map, dynamically adding or removing value is what we usually do instead ofspecifying it during creation.

1 var colors = {};

2

3 colors.red = 'Red';

4 colors['blue'] = 'Blue'; // another form

5

6 delete colors.blue;

You may wonder what the difference is between using dot and square bracket. Thisexample can clearly tells.

Page 58: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 53

1 var colors = {

2 red: 'Red'

3 };

4

5 var colorToPick = 'red'

6 console.log(colors[colorToPick]);

7 // -> 'Red'

The square bracket usage on accessing object property allows you to dynamically accessany property based on a variable, whose value is resolved to be property name.

Native Map

In ES6, a new data type, Map, is introduced so that you don’t need to use Object tosimulate a Map. There are some benefits of using Map over Object:

1. The properties of Objectmust be String or Symbols (Symbol is not widely supportedand so not discussed in this book). But for Map, it can be anything.

2. It’s very easy to get the size from a Map, while you have to manually keep track ofit for Object.

Notes: Be aware of the for ... of usage here. It can only be used on iterable objects likeArray, Map, Set, etc.

1 function happy() {

2 console.log('Happy everyday.');

3 }

4

5 var map = new Map();

6

7 map.set(NaN, 'I am not a Number');

8 map.set(621, 'My birthday');

9 map.set(happy, 'Happy Function');

10

11 console.log(map.get(NaN)); // -> 'I am not a Number'

12 console.log(map.size); // -> 3

13

14 for (var key of map.keys()) {

15 console.log(key);

16 }

17 // -> NaN

Page 59: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 54

18 // -> 621

19 // -> [Function: happy]

20

21 for (var value of map.values()) {

22 console.log(value);

23 }

24 // -> 'I am not a Number'

25 // -> 'My birthday'

26 // -> 'Happy Function'

5.4 Set

Set is similar to Array, but it has a very special feature. The values stored in it are unique.Even if you try adding same value (primitive value or object reference), it only keeps one.

1 var uniqueData = new Set();

2

3 uniqueData.add(621);

4 uniqueData.add('Ken');

5 uniqueData.add(621);

6 uniqueData.add({name: 'Tasting JavaScript'});

7

8 console.log(uniqueData.size); // -> 3

9

10 for (var value of uniqueData.values()) { // uniqueData.keys() has same effect

11 console.log(value);

12 }

13 // -> 621

14 // -> Ken

15 // -> { name: 'Tasting JavaScript' }

5.5 String

Interpolation

When we learned about String in chapter 2, we knew that + can be used as concatenationoperator to combine multiple strings together, especially there are some dynamic textswhose values are from variables.

In ES6, there is one more elegant way to do so. By using String interpolation, you justneed to define a text template, and the variable value can be automatically resolvedwithin it.

Page 60: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 55

1 var name = {

2 firstName: 'Ken',

3 lastName: 'Chen'

4 };

5

6 var birthday = '21, Jun';

7

8 console.log(`I am ${name.firstName} ${name.lastName}. My birthday is ${birthday\

9 }.`);

10 // -> I am Ken Chen. My birthday is 21, Jun.

Notes: the String Interpolation is using backtick \‘ instead of quotes.

Methods

Besides concatenation, there are some common operations for String. As String isimmutable, all belowmethods do notmodify the original string but returns themassagednew value.

1. trim helps to remove all the whitespace characters (space, tab, etc.) and lineterminator characters (LF, CR, etc.) from both ends of a string.

2. toUpperCase and toLowerCase converts the string to all in upper case or lower case.3. split method splits a string into array based on some the seperator provided. If

you still remember, Array data type has counterpart method join to join an arrayinto String.

4. indexOf and lastIndexOf tells the index position of the first occurrence of thespecified sub-string in the string to search from. -1 indicates that sub-string is notfound.

5. charAt obtains the char in specified index from a string6. substring extracts a subset of a string between the starting index position and

optionally the end index.7. substr extracts a subset of a string beginning at the specified index position with

an optionally provided length of the sub-string.

Page 61: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 56

1 var stringMassaged = '';

2

3 var stringWithSpace = ' I am too verbose. \t ';

4 stringMassaged = stringWithSpace.trim();

5

6 console.log(stringWithSpace.length); // -> 21

7 console.log(stringMassaged); // -> I am too verbose.

8 console.log(stringMassaged.length); // -> 17

9

10 var mixCases = 'mIx AnD mAtCh';

11 console.log(mixCases.toUpperCase()); // -> MIX AND MATCH

12 console.log(mixCases.toLowerCase()); // -> mix and match

13

14 var numbers = '1,2,3,4,5';

15 console.log(numbers.split(',')) // -> [ '1', '2', '3', '4', '5']

16

17 var sentence = 'I am not a great programmer; I am just a good programmer with gr\

18 eat habits. - Kent Beck';

19

20 console.log(sentence.indexOf('program')); // -> 17

21 console.log(sentence.lastIndexOf('programmer')); // -> 46

22 console.log(sentence.lastIndexOf('coder')); // -> -1

23

24 console.log('JavaScript'.charAt(4)); // -> S

25 console.log(sentence.substring(0, sentence.indexOf(';')))

26 // -> I am not a great programmer

27 console.log(sentence.substr(sentence.lastIndexOf('I'), 45))

28 // -> I am just a good programmer with great habits

5.6 Exercises

Month Name Resolver

Please write a function getMonthNamewhich takes a numericmonth value and then returnsthe month name based on the array of month data provided as below.

Page 62: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 57

1 var months = [

2 {month: 1, name: 'Jan'}, {month: 2, name: 'Feb'},

3 {month: 3, name: 'Mar'}, {month: 4, name: 'Apr'},

4 {month: 5, name: 'May'}, {month: 6, name: 'Jun'},

5 {month: 7, name: 'Jul'}, {month: 8, name: 'Aug'},

6 {month: 9, name: 'Sep'}, {month: 10, name: 'Oct'},

7 {month: 11, name: 'Nov'}, {month: 12, name: 'Dec'}

8 ];

Array to Map

Sometimes, we need to convert an array to map in order to quickly lookup some value.For example, above month name resolver exercise requires us to loop through thearray and check which value matches the numeric month provided. However, if we takeadvantage of the concept of Object as Map, it’s easier to lookup the month name.

Please write a function arrayToMap(data, keyProperty, valueProperty) by taking threeparameters so that calling arrayToMap(months, 'month', 'name') can provide result asbelow. And also rewrite the getMonthName function to use it.

1 { '1': 'Jan',

2 '2': 'Feb',

3 '3': 'Mar',

4 '4': 'Apr',

5 '5': 'May',

6 '6': 'Jun',

7 '7': 'Jul',

8 '8': 'Aug',

9 '9': 'Sep',

10 '10': 'Oct',

11 '11': 'Nov',

12 '12': 'Dec' }

Matrix Convertor

There is no data type in JavaScript to exactly represent a matrix. As matrix is also acollection of data, many people use Array to represent a matrix.

If we directly use flat array [1, 2, 3, 4, 5, 6, 7, 8, 9], then there is no obvious signthat it’s matrix. Hence, the matrix structure must be represented somewhere else.

Another way to use array to represent a matrix is embedding array into array: [[1, 2,

3], [4, 5, 6], [7, 8, 9]].

Pleasewrite two functions: matrixArrayToMatrixObj(matrixArray) and matrixObjToMatrixAr-

ray(matrixObj). Their functionalities are as below:

Page 63: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Data Structure 58

1 var matrixObj = {

2 rows: 2,

3 columns: 4,

4 data: [1, 2, 3, 4, 5, 6, 7, 8]

5 };

6

7 var matrixArray = [[1, 2, 3, 4], [5, 6, 7, 8]];

8

9 // Should produce result in same structure as matrixObj

10 matrixArrayToMatrixObj(matrixArray);

11

12 // Should produce result in same structure as matrixArray

13 matrixObjToMatrixArray(matrixObj);

Page 64: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

6. Object-orientedObject-oriented programming, whose essence is nothingmore than program-ming using data with associated behaviors, is a powerful idea. It truly is. Butit’s not always the best idea. � Sometimes data is just data and functions arejust functions. – Rob Pike

When entering the world of programming language, you will see many terms of pro-gramming paradigm, such as object-oriented programming, functional programming,declarative programming, imperative programming. Don’t let these words scare youaway. We just need to pick the most basic and important concepts at the beginning andyou will gradually see the difference especially when you learned different kinds of thelanguage.

The huge wave of hype for Object-oriented programming starts around 1990. OOPconcepts and design patterns became hottest interview questions for a long time. Somelanguages are considered “pure” OO language because everything in it is modeled as anobject, such as Smalltalk, Ruby, Scala. Some languages are not pure but mainly use OOparadigm, such as Java, Objective C, C++, C#.

OOP is not the only way to program but it’s good to know what it is and in which scenarioit’s best used.

6.1 Core concepts

Simply put, it’s based on “object” modeling. An object contains attributes and behaviors.The object model is easy for human to understand. For example, if we model the caras an object, it has attributes like color, number of seats, volume of oil tank, etc. Start,run and stop are its behavior. It’s composed of sub-objects too, a body, an engine, fourwheels, etc. The sub-objects can also have their own attributes and behaviors too.

Below are three core concepts of OOP.

• Encapsulation• Inheritance• Polymorphism

Page 65: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 60

6.2 Encapsulation

Encapsulation is usually used for describing below two notions.

1. Object structure that bundles attributes and behaviors together.2. Mechanism for restricting direct access to some of the object attributes.

If we want to model a book shelf in JavaScript, we can use an array and each object in itis a book as below.

1 var bookShelf = []

2

3 bookShelf.push({

4 name: 'Tasting JavaScript',

5 author: 'Ken Chen'

6 })

7 bookShelf.push({

8 name: 'Rework',

9 author: 'Jason Fried and David Heinemeier Hansson'

10 })

11 bookShelf.push({

12 name: 'Structure and Interpretation of Computer Programs',

13 author: 'Harold Abelson and Gerald Jay Sussman'

14 })

However, there are some issues here:

1. The bookShelf is an raw array and each book is just simple object. There is no specificobject type information with it.

2. The bookShelf can bemanipulated easily with any arraymethods. How can I restrictit to only have some specialized methods, like addBook, removeBook, etc.

These questions are what encapsulation can help to address.

Constructor

Constructor can help us to create a object instance for a particular object type, like atemplate or mold. Constructor is just a JavaScript function, but we call it differently witha new keyword. As convention, if a function is intended to be used as a constructor, itsname should be capitalized.We can define two Constructors BookShelf and Book as below.

Page 66: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 61

1 function BookShelf() {

2 this.books = []

3

4 this.addBook = function(book) {

5 this.books.push(book)

6 }

7

8 this.removeBook = function(name) {

9 for (var i = 0; i < this.books.length; i++) {

10 if (this.books[i].name === name) {

11 this.books.splice(i, 1)

12 break

13 }

14 }

15 }

16 }

17

18 function Book(name, author) {

19 this.name = name

20 this.author = author

21 }

22

23 var bookShelf = new BookShelf()

24 var book1 = new Book('Tasting JavaScript', 'Ken')

25 var book2 = new Book('Rework', 'Jason Fried and David Heinemeier Hansson')

26 var book3 = new Book(

27 'Structure and Interpretation of Computer Programs',

28 'Harold Abelson and Gerald Jay Sussman'

29 )

30

31 bookShelf.addBook(book1)

32 bookShelf.addBook(book2)

33 bookShelf.addBook(book3)

34 console.log(bookShelf.books.length)

35 // -> 3

36

37 bookShelf.removeBook('Tasting JavaScript')

38 console.log(bookShelf.books.length)

39 // -> 2

40

41 console.log(bookShelf instanceof BookShelf)

42 // -> true

Page 67: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 62

43 console.log(bookShelf)

44 // -> BookShelf {

45 // -> books:

46 // -> [ Book {

47 // -> name: 'Rework',

48 // -> author: 'Jason Fried and David Heinemeier Hansson' },

49 // -> Book {

50 // -> name: 'Structure and Interpretation of Computer Programs',

51 // -> author: 'Harold Abelson and Gerald Jay Sussman' } ],

52 // -> addBook: [Function],

53 // -> removeBook: [Function] }

There are a couple of advantages here as you can see:

1. It’s easier to see that there are two object type BookShelf and Book and whatattributes or behaviors each object type has.

2. Customized behaviors addBook and removeBook now can be supported.3. When we print out the object, it’s more user-friendly with the constructor name at

the beginning.

Here we also introduced a new operator instanceof which tells you whether an object isa particular type.

However, we can still freely access the books attribute of bookShelf and use the arraymethods to change it. How can we hide it from the outside? We can change the BookShelf

constructor as below.

1 function BookShelf() {

2 var books = [] // Define a local variable instead of using this

3

4 this.addBook = function(book) {

5 books.push(book)

6 }

7

8 this.removeBook = function(name) {

9 for (var i = 0; i < books.length; i++) {

10 if (books[i].name === name) {

11 books.splice(i, 1)

12 break

13 }

14 }

15 }

Page 68: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 63

16

17 this.bookCount = function() {

18 return books.length

19 }

20 }

21

22 // Omitted Book constructor and adding books' statements for brevity

23

24 console.log(bookShelf.books)

25 // -> undefined

26 console.log(bookShelf.bookCount())

27 // -> 3

Getter and Setter

Besides using constructor, there is one simpler way to implement encapsulation if youhave special logics on the object property, say it cannot be changed or is computed basedon other properties.

1 var person = {

2 firstName: 'Ken',

3 lastName: 'Chen',

4 get fullName() {

5 return this.firstName + ' ' + this.lastName

6 },

7 set fullName(fullName) {

8 var names = fullName.split(' ')

9

10 this.firstName = names[0]

11 this.lastName = names[1]

12 }

13 }

14

15 console.log(person.fullName)

16 // -> Ken Chen

17

18 person.fullName = 'Winnie Su'

19

20 console.log(person.firstName)

21 // -> Winnie

22 console.log(person.lastName)

23 // -> Su

Page 69: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 64

We can also use Object.definemethod to add getter and setter to existing object. But tobe noted that if we don’t provide a setter with the getter definition together, trying toupdate the property takes no effect.

1 var person = {

2 firstName: 'Ken',

3 lastName: 'Chen'

4 }

5

6 Object.defineProperty(person, 'fullName', {

7 get: function() {

8 return this.firstName + ' ' + this.lastName

9 }

10 })

11

12 console.log(person.fullName)

13 // -> Ken Chen

14

15 person.fullName = 'Winnie Su'

16 console.log(person.fullName)

17 // -> Ken Chen

Enumerable vs Non-enumerable

In chapter 5, we learned about how to enumerate the object properties by using for ...

in ... statement. Let’s see what we got on object person.

1 var person = {

2 firstName: 'Ken',

3 lastName: 'Chen'

4 }

5

6 Object.defineProperty(person, 'fullName', {

7 get: function() {

8 return this.firstName + ' ' + this.lastName

9 }

10 })

11

12 for (var i in person) {

13 console.log(i)

14 }

15 // -> firstName

16 // -> lastName

Page 70: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 65

Why the fullName is not listed? Actually, each property of the object have an enumerable

attribute which defines whether it should be listed when using for ... in ... loop. Thedefault value of that attribute is false if it’s not explicitly specified. We can set it as belowto make it enumerable.

1 var person = {

2 firstName: 'Ken',

3 lastName: 'Chen'

4 }

5

6 Object.defineProperty(person, 'fullName', {

7 get: function() {

8 return this.firstName + ' ' + this.lastName

9 },

10 enumerable: true

11 })

12

13 for (var i in person) {

14 console.log(i)

15 }

16 // -> firstName

17 // -> lastName

18 // -> fullName

6.3 Inheritance

Inheritance is that one object inherit same behaviors or attributes from another object.It’s a mechanism for code reuse and the inheritance relationship also forms a hierarchy.The IS-A relationship is often used by people to evaluate whether two objects have validinheritance relationship.

For example, cat is an animal; dog is also an animal. Hence, we can build an inheritancerelationship model from cat to animal and from dog to animal. Cat and dog objects arechild; animal object are parent in the inheritance hierarchy.

Prototype

In JavaScript, the root of the hierarchy is Object. Its toStringmethod is accessible for anyobject.

Page 71: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 66

1 var obj = {}

2

3 console.log(obj.toString)

4 // -> [Function: toString]

5 console.log(obj instanceof Object)

6 // -> true

How can we access a property which is not defined in the object? It’s through thePrototype Chain which implements the inheritance in JavaScript. Let’s have a visual ideaon how it looks like through below diagram and sample code.

JS prototype chain

1 function Bird(type) {

2 this.type = type

3 }

4

5 Bird.prototype.fly = function() {

6 console.log('Flying with two wings')

7 }

8

9 // Bird Instance

10 var hummingbird = new Bird('Hummingbird')

11 var swan = new Bird('Swan')

12

13 console.log(hummingbird.type)

14 // -> Hummingbird

15 console.log(swan.type)

16 // -> Swan

17

18 // Search up the chain and find in Bird.prototype

Page 72: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 67

19 hummingbird.fly()

20 // -> Flying with two wings

21

22 console.log(hummingbird.fly === swan.fly)

23 // -> true

24

25 // Search up the chain and find in Object.prototype

26 console.log(hummingbird.valueOf())

27 // -> Bird { type: 'Hummingbird' }

1. Property type is defined per Bird instance base as usual.2. The new usage is that the fly method is defined on the property prototype of Bird

constructor. Actually, every function has a prototype object property. The propertiesdefined on it are shared across all object instances created by this constructor.

3. When we access the flymethod of hummingbird, it doesn’t exist in the instance itself.However, JavaScript will check on the implicit __proto__ property of hummingbird andthis property actually points to the prototype property of Bird constructor.When fly

method is located, the search ends.4. Same mechanism applies on searching the valueOf method and it ends on the

prototype property of Object constructor.

This is how JavaScript implements the inheritance mechanism and why it’s calledPrototype Chain. The implicit __proto__ property in object instances and the prototype

objects forms the Prototype Chain from the bottom till the top in Object.

Override

I am so naive that I originally thought that all birds can fly. However, I found out later thatsome birds cannot, such as penguins. How can I override the default behavior inheritedfrom Bird prototype?

As we share before, the properties are looked up through Prototype Chain, hence we cansimply override the default behavior by assigning a new property with the same nameto the object itself. The original one in prototype will not be affected.

Page 73: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 68

1 function Bird(type) {

2 this.type = type

3 }

4

5 Bird.prototype.fly = function() {

6 console.log('Flying with two wings.')

7 }

8

9 var penguin = new Bird('Penguin')

10 var swan = new Bird('Swan')

11

12 penguin.fly = function() {

13 console.log('Flying with two wings in the water but not sky.')

14 }

15

16 penguin.fly()

17 // -> Flying with two wings in the water but not sky.

18 swan.fly()

19 // -> Flying with two wings.

Assigning new properties to object will never change the one in its constructor’s proto-type. However, modifying the property is different. As the properties of the prototype areshared across all instances, if they are object or array type, modifying them can affectsall the instances immediately.

1 function Bird(type) {

2 this.type = type

3 }

4

5 Bird.prototype.colors = []

6

7 var swan = new Bird('Swan')

8 swan.colors.push('Black')

9

10 var parrot = new Bird('Parrot')

11 parrot.colors.push('Purple')

12

13 console.log(swan.colors)

14 // -> [ 'Black', 'Purple' ]

As you can see, now the swan object instance is also changed. swan has color Purple too.Hence, the thumb of rule is that if the property is most likely changed for every instance,

Page 74: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 69

it should be placed inside the constructor using this to initialize it. Only those commonlyshared but less-likely changed properties should be placed in prototype especially whenit’s object type.

Self-defined inheritance relationship

Previously, we only have two levels of inheritance from object instance to constructor,to Object. Can we expand the inheritance hierarchy to have more levels? For example,I want to define three constructors: Swan and Penguin as the child of Bird; BlackSwan asthe child of Swan. In this way, I don’t have to specify same information repeatedly whencreating new instances for each type of the bird.

We can achieve that by explicitly setting the prototype object for each constructor.

1 function Bird(type) {

2 this.type = type

3 }

4

5 function Penguin() {

6 Bird.call(this, 'Penguin')

7 }

8 Penguin.prototype = Object.create(Bird.prototype)

9

10 function Swan(color) {

11 this.color = color || 'White'

12 Bird.call(this, 'Swan')

13 }

14 Swan.prototype = Object.create(Bird.prototype)

15

16 function BlackSwan() {

17 Swan.call(this, 'Black')

18 }

19 BlackSwan.prototype = Object.create(Swan.prototype)

20

21 var penguin = new Penguin()

22 var swan = new Swan()

23 var blackSwan = new BlackSwan()

24

25 console.log(penguin)

26 // -> Bird { type: 'Penguin' }

27 console.log(swan)

28 // -> Bird { color: 'White', type: 'Swan' }

29 console.log(blackSwan)

Page 75: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 70

30 // -> Bird { color: 'Black', type: 'Swan' }

31 console.log(penguin instanceof Bird)

32 // -> true

33 console.log(blackSwan instanceof Bird)

34 // -> true

35 console.log(blackSwan instanceof Swan)

36 // -> true

Two new things that deserved some explanation here:

1. In child constructor Penguin, Swan and BlackSwan, the corresponding parent con-structor need to be called using the form xxx.call(this, 'yyy'). The this identifierrefers to the Penguin, Swan and BlackSwan object instance when created using new. Sowhen it’s provided to the parent constructor call, the properties initialized in Bird

or BlackSwan are set to that object accordingly. And other necessary parameters canalso be passed accordingly.

2. The prototype of the child constructor need to be derived from the prototype

property of the desired constructor instead of Object. Here, we use Object.create

to clone a new object based on the provided prototype.

6.4 Polymorphism

When different objects have same interface but different behaviors, and an operationsupports any object as long as it has the expected interface, this operation is a polymor-phic type and this technique is called Polymorphism.

console.log is a very good example of Polymorphism. When you pass a function, arrayor object to it, it works without any change. Function, Array and Object all have its ownvalueOf interface but behaves differently so that the result printed on screen is different.SubTyping through Inheritance is a very typical approach in Polymorphism.

We can see below Bird example on their common fly interface.

1 function Bird(type) {

2 this.type = type

3 }

4 Bird.prototype.fly = function() {

5 console.log(this.type + ': Flying with two wings in the immense sky.')

6 }

7

8 function Penguin() {

9 Bird.call(this, 'Penguin')

Page 76: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 71

10 }

11 Penguin.prototype = Object.create(Bird.prototype)

12 Penguin.prototype.fly = function() {

13 console.log(this.type + ': What? You don't know I cannot fly?')

14 }

15

16 function Swan(color) {

17 Bird.call(this, 'Swan')

18 }

19 Swan.prototype = Object.create(Bird.prototype)

20

21 function flyingContest(candidates) {

22 for (var i = 0; i < candidates.length; i++) {

23 candidates[i].fly()

24 }

25 }

26

27 var penguin = new Penguin()

28 var swan = new Swan()

29

30 flyingContest([swan, penguin])

31 // -> Swan: Flying with two wings in the immense sky.

32 // -> Penguin: What? You don't know I cannot fly?

6.5 Exercises

Whac-A-Mole

My son likes to play this game very much when he’s four-years’ old. So let’s write asimplified command-line version of this game.

Page 77: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 72

Whac-A-Mole

As this is a command line program. How can we simulate this game? To make it simple,we can display a table as below. The O are the holes while the M is the mole shown. Afterthe table is shown, you have five seconds to input the X-Y coordinate position of themoleand press Enter (In the format of X,Y and 2,3 is for below case). If it’s correct, then youget one score. After five seconds, the mole shows in another hole.

Page 78: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 73

1 | O | O | O | O |

2 | O | M | O | O |

3 | O | O | O | O |

4 | O | O | O | O |

If we consider this game is an Object, what attributes and behaviors it should have? Ithink it should at least have below attributes and behaviors (You can add any assistanceattributes or behaviors as you need to facilitate your logic):

• Attributes:

1. score: Used to keep track of how many moles you hit.• Behaviors:

1. printResult: Prints out the exit message with score when the program isterminated (Ctrl+C is pressed).

2. showHoles: Prints out the table with a randomly shown mole.3. isMoleHit: Checks if you hit the right mole and increase the score if needed.

So few attributes? That is also the beauty of Encapsulation. You should only provide publicinterface and leave all implementation detail inside.

1 'use strict'

2

3 // Creates your WhacAMole constructor with attributes and behaviors

4 function WhacAMole(width, height) {

5

6 }

7

8 // You should have no need to modify below code

9 var obj = new WhacAMole()

10

11 obj.showHoles()

12

13 var i = setInterval(function() {

14 obj.showHoles()

15 }, 5000) // 5000 milliseconds which means 5 seconds

16

17 process.stdin.setEncoding('utf8')

18

19 process.stdin.on('readable', () => {

Page 79: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Object-oriented 74

20 var chunk = process.stdin.read()

21 if (chunk !== null) {

22 chunk = chunk.toString()

23 // isMoleHit accepts your input after pressing Enter

24 obj.isMoleHit(chunk.substring(0, chunk.length - 1))

25 }

26 })

27

28 process.on('SIGINT', function() {

29 clearInterval(i)

30 // Prints out the exit message and score

31 obj.printScore()

32

33 process.exit(0)

34 })

35

36 function getRandomIntInclusive(min, max) {

37 return Math.floor(Math.random() * (max - min + 1)) + min

38 }

Hints: String’s split method; two dimensional array ([[‘X’, ‘X’], [‘X’, ‘X’]]) can be used tosimulate the table.

Page 80: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

7. Functional ProgrammingAll problems in computer science can be solved by another level of indirec-tion. – David Wheeler

During the hype of Object-oriented programming, many people claims it’s the only wayand the right way to program. However, it’s not the case. If we program and model theworld all based on Object, it introduces unnecesary complexity. And that is why manypeople complain about the verbosity of Java, unneeded layers introduced by designpatterns.

Functional Programming rises and gains more popularity after that because it has greatadvantages on parallel computing and distributed systems.

7.1 Core concepts

The two most important concepts in Functional Programming are:

• First-class & Higher-order Function• Pure Function

First-class & Higher-order Function

What does it mean? Basically, they are similar. Higher-order functions, more from amathematical concept, describe the functions that can operate on other functions. WhileFirst-class functions, more from computer science concept, means the language allowsthe functions to be used anywhere in the program like other first-class entities, such asnumbers, strings. They can be arguments to other functions or as other functions’ returnvalue.

Let’s see an example. To deal with Array-like objects, we normally use a for loop to iterateon each item in it and do some operation. Can we extract the for loop from the actualwork so that we don’t need to write that every time?

Page 81: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 76

1 var numbers = [1, 2, 3, 4, 5];

2

3 function double(num) {

4 return num * 2;

5 }

6

7 function square(num) {

8 return num * num;

9 }

10

11 function map(data, fn) {

12 var results = [];

13

14 for (var i = 0; i < data.length; i++) {

15 results.push(fn(data[i]));

16 }

17

18 return results;

19 }

20

21 console.log(map(numbers, double));

22 // -> [ 2, 4, 6, 8, 10 ]

23 console.log(map(numbers, square));

24 // -> [ 1, 4, 9, 16, 25 ]

As you can see, double and square functions are treated as normal parameter. Functionmap, as Higher-order function, is responsible for iterating the array items and call thepassed-in fn function parameter to process each item in the array.

I will show you the example of using function as a return value in sectionCurrying below.

Pure Function

In what condition, we can say that a function is pure?

1. Returns the same result value given the same argument value.The function should not depend on hidden state of the evironment, anything mightchange during different executions or input from I/O devices

2. Causes no side effects.The function doesn’t mutate external objects, state or output to I/O devices.

Making a function pure has many benefits:

Page 82: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 77

1. Its behavior is expectable and less error-prone because its result is constant giventhe same arguments.

2. If a function is pure, and its return result is not used, it can be removed safely.3. Pure functions should not interfere each other and their execution order can be

freely arranged or performed in parallel if they don’t need to use each other’s resultas parameter.

7.2 Composition

As what I emphasized in chapter 4 that composing clear and concise functions togetherto accomplish one thing is better than writing a single large one. Composition helps tomake the program more expressive. For example, I want to write programs to filter outfrom a sequence of numbers which are even, or divisible by 6.

1 var seq = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

2 var filtered = [];

3 for (var i = 0; i <= seq.length; i++) {

4 if (seq[i] % 2 == 0) {

5 filtered.push(i);

6 }

7 }

8 console.log(filtered)

9 // -> [ 0, 2, 4, 6, 8, 10 ]

10

11 seq = [2, 4, 6, 8, 10, 12, 14, 16, 18];

12 filtered = [];

13 for (var i = 0; i <= seq.length; i++) {

14 if (seq[i] % 6 == 0) {

15 filtered.push(i);

16 }

17 }

18 console.log(filtered)

19 // -> [ 6, 12, 18 ]

How many common patterns you can see from above two program segments? I think atleast two there.

1. Number sequence generation2. Filtering logic.

If we refactor the code as below, what do you think?

Page 83: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 78

1 function sequence(max, min, step) {

2 var seq = []

3 for (var i = min || 0; i <= max; i = i + (step || 1)) {

4 seq.push(i)

5 }

6 return seq

7 }

8

9 function filter(seq, cond) {

10 var filtered = []

11 for (var i = 0; i <= seq.length; i++) {

12 if (cond(seq[i])) {

13 filtered.push(seq[i])

14 }

15 }

16 return filtered

17 }

18

19 function isEven(num) {

20 return num % 2 == 0

21 }

22

23 filter(sequence(10), isEven)

24

25 filter(sequence(18, 2, 2), function(num) {

26 return num % 6 == 0

27 })

At first glance, you may think I have doubled the program size and made the codeunnecessary complex. However, there are couples of advantages here:

1. Three function units sequence, filter and isEven are common abstractions that areallowed to be individually reused for other scenarios.

2. Composition makes the code more expressive at first glance, seven lines of codevs filter(sequence(10), isEven).

7.3 Functional behaviors on Array

Actually, the map and filter function I defined above are standard methods on arrays.Those programs can be revised as below.

Page 84: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 79

1 // function sequence, isEven, double, square are omitted here for brevity.

2

3 console.log(sequence(5, 1).map(double))

4 // -> [ 2, 4, 6, 8, 10 ]

5 console.log(sequence(5, 1).map(square))

6 // -> [ 1, 4, 9, 16, 25 ]

7

8 console.log(sequence(10).filter(isEven))

9 // -> [ 0, 2, 4, 6, 8, 10 ]

10 console.log(sequence(18, 2, 2).filter(function(num) {

11 return num % 6 == 0

12 }))

13 // -> [ 6, 12, 18 ]

Two more standard methods defined on arrays, forEach and reduce, are very useful.forEach is similar to map, but it just executes the function on each item in array withoutreturning a processed value.

For method forEach, filter and map, the function we provided to it can actually take threearguments: currentValue, index, array. You can access the index of current value in arrayand the array itself in the function as well.

1 sequence(10).forEach(function(value, idx, array) {

2 console.log(value + ' is at position ' + idx)

3 })

4 // -> 0 is at position 0

5 // -> 1 is at position 1

6 // -> ...

7 // -> 10 is at position 10

For method reduce, it’s a little bit different. The return value for method forEach, filter,map is always an array, while reduce can return anything. The return value of reduce can bea single primitive value or an object. It emphasize more on the value as a whole insteadof a collection of each processed value.

Let’s use it to sum a sequence of numbers.

Page 85: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 80

1 var sum = sequence(10).reduce(

2 function(previousValue, currentValue, currentIndex, array) {

3 return previousValue + currentValue

4 }, 0)

5

6 console.log(sum)

7 // -> 55

The reduce method takes two parameters, the first one is the function and the secondone is the initial value. Although the initial value is optional, I strongly recommendedthat it’s provided. Because you can clearly tell what the expected output data structureis and the function behavior is more expectable.

As demonstrated above, the function provided to reduce method takes four argumentsalthoughwenormally use the first two.When the loop starts at index 0, the previousValueis the initial value and currentValue is the first element in the array. Then the loopscontinues at index 1, the previousValue becomes the result return from last functionexecution, which in this case is the sum of the initial value and element at index 0, andthe currentValue becomes the second element in the array. So on and so forth. Themostimportant thing to pay attention is that you must always return a value in the functionas the previousValue for next loop.

Now you learn these basic methods for Array, let’s see how expressive it can be.

1 var result = sequence(10)

2 .map(square)

3 .filter(function(num) {

4 return num % 5 == 0

5 })

6 .reduce(function(sum, value, index) {

7 sum[index] = value

8 return sum

9 }, {})

10

11 console.log(result)

12 // -> { '0': 0, '1': 25, '2': 100 }

7.4 Closure

This topic should be the most frequently asked questions during interview for junior or2∼3 years experienced JavaScript developers. Hence, this is an important concept andit’s a little bit abstract and difficult. It’s OK if you don’t completely understand at the firsttime. You can revisit it from time to time.

Page 86: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 81

Let’s first see what does Closuremeans. Below is the defintion from MDN1:

Closures are functions that refer to independent (free) variables (variablesthat are used locally, but defined in an enclosing scope). In other words, thesefunctions ‘remember’ the environment in which they were created.

As usual, the concept is very abstract. But I have highlighted the key points. Let’s see howit’s used in some practical examples so that you can understand it better.

Common Examples

Markdown2 allows us to use plain text with some simple syntax to create structural HTMLand is widely used in article, blog, and book writing, including this one.

In the Markdown syntax, if you start a line with #, it’s the first-level header; If you start aline with ##, it’s the second-level header. So on and so forth to header level 6.

So, if I want to have some functions to convert text to different header, we can write itthis way:

1 function h1(text) {

2 return '# ' + (text ? text : '')

3 }

4

5 function h2(text) {

6 return '## ' + (text ? text : '')

7 }

8

9 function h3(text) {

10 return '### ' + (text ? text : '')

11 }

But you see, there are some duplicate empty text checking code and the only differencethere is the markdown syntax prefix part. We can refactor in this way normally.

1https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures2https://daringfireball.net/projects/markdown/

Page 87: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 82

1 function defaultText(text) {

2 return (text ? text : '')

3 }

4

5 function h1(text) {

6 return '# ' + defaultText(text)

7 }

8

9 function h2(text) {

10 return '## ' + defaultText(text)

11 }

12

13 function h3(text) {

14 return '### ' + defaultText(text)

15 }

However, there is still one duplicate part ‘ + defaultText(text)‘. Can we make a stepfurther? Let’s see the magic below.

1 function defaultText(text) {

2 return (text ? text : '')

3 }

4

5 function markdownHeader(prefix) {

6 return function(text) {

7 return prefix + ' ' + defaultText(text)

8 }

9 }

10

11 var h1 = markdownHeader('#')

12 var h2 = markdownHeader('##')

13 var h3 = markdownHeader('###')

14

15 console.log(h1('One')) // -> '# One'

16 console.log(h2('Two')) // -> '# Two'

17 console.log(h3('Three')) // -> '# Three'

The h1, h2 and h3 are closures. They are the functions created by function markdownHeader.This actually is one design pattern, called Factory Pattern, but our focus is not on thisnow. The point is the inner function in markdownHeader is partially provided requiredinformation for later processing and so h1, h2 and h3 remembers the prefix we passedin when they are created. Partial Application is a commonly used scenario of closures.

There is one more approach for Partial Application without using closures.

Page 88: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 83

1 function defaultText(text) {

2 return (text ? text : '')

3 }

4

5 function markdownHeader(prefix, text) {

6 return prefix + ' ' + defaultText(text)

7 }

8

9 var h1 = markdownHeader.bind(null, '#')

10 var h2 = markdownHeader.bind(null, '##')

11 var h3 = markdownHeader.bind(null, '###')

12

13 console.log(h1('One')) // -> '# One'

14 console.log(h2('Two')) // -> '# Two'

15 console.log(h3('Three')) // -> '# Three'

As we saw before, the bind method allows us to specify the object to be used if thefunction refers this in it. In the case above, we don’t care about the this object and sowe bind a null to it. But bindmethod also allows us to preset any number of parametersfor the function.

Let’s see another example on using closure. Sometimes, we would like to measure howmuch time one JavaScript function takes to run. A simple way is to measure as below.

1 function seemsSlow(times, msg) {

2 var start = new Date()

3

4 // Some work to do here.

5 for (var i = 0; i < times; i++) {

6 }

7

8 return msg

9

10 var end = new Date()

11 var duration = ((end - start) / 1000)

12

13 console.log(`This function runs for ${duration} second.`)

14 }

15

16 console.log(seemsSlow(1000000000, 'Done'))

17 // -> This function runs for 0.556 second.

18 // -> Done

Page 89: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 84

However, if we have to modify the function source code in order to measure it, it isinefficient and error-prone. Can we abstract that out?

1 function measure(fn) {

2 return function() {

3 var start = new Date()

4

5 var result = fn.apply(null, arguments)

6

7 var end = new Date()

8 var duration = ((end - start) / 1000)

9

10 console.log(`This function runs for ${duration} second.`)

11

12 return result

13 }

14 }

15

16 function seemsSlow(times, msg) {

17 for (var i = 0; i < times; i++) {

18 }

19

20 return msg

21 }

22

23 var wrappedFn = measure(seemsSlow)

24 console.log(wrappedFn(1000000000, 'Done'))

25 // -> This function runs for 0.528 second.

26 // -> Done

Function measure wraps the fn into a new function with timing capability. One thing to benoticed is that if we simply use fn() instead of the statement var result = fn.apply(this,

arguments), we lost the capabilities of accepting arguments and returning value of the fn.Method apply of Function is helpful in this case. It accepts two arguments: the first oneas the this value; the second one, an Array-like objects, as the arguments for the fn. Itsreturn value is the return value of original fn function.

Common Mistake

Let’s check below code and can you tell what the output is?

Page 90: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 85

1 var headerFns = [

2 {methodName: 'h1', headerPrefix: '#'},

3 {methodName: 'h2', headerPrefix: '##'},

4 {methodName: 'h3', headerPrefix: '###'}

5 ]

6

7 var markdownHeader = {}

8 for (var i = 0; i < headerFns.length; i++) {

9 var fn = headerFns[i]

10 markdownHeader[fn.methodName] = function(text) {

11 return fn.headerPrefix + ' ' + text

12 }

13 }

14

15 console.log(markdownHeader.h1('One'))

16 console.log(markdownHeader.h2('Two'))

17 console.log(markdownHeader.h3('Three'))

18 // -> ??

It’s not this of course since I asked.

1 # One

2 ## Two

3 ### Three

It’s like this:

1 ### One

2 ### Two

3 ### Three

var is not used for scope level variable declaration. Above code actually is same as below.The variable fn is lifted up.

Page 91: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 86

1 var headerFns = [

2 {methodName: 'h1', headerPrefix: '#'},

3 {methodName: 'h2', headerPrefix: '##'},

4 {methodName: 'h3', headerPrefix: '###'}

5 ]

6

7 var markdownHeader = {}

8 var fn

9

10 for (var i = 0; i < headerFns.length; i++) {

11 fn = headerFns[i]

12 markdownHeader[fn.methodName] = function(text) {

13 return fn.headerPrefix + ' ' + text

14 }

15 }

16

17 console.log(markdownHeader.h1('One'))

18 console.log(markdownHeader.h2('Two'))

19 console.log(markdownHeader.h3('Three'))

Hence, the for loop keeps changing on the value fn points to. All three closures createdpoints to the same object in the last position of the array. One simple way to fix this issueis replacing the var to let.

However, if the environment doesn’t support let, what can we do? We need to createanother level of closure.

1 function markdownHeaderFn(headerObj) {

2 return function(text) {

3 return headerObj.headerPrefix + ' ' + text

4 }

5 }

6

7 var headerFns = [

8 {methodName: 'h1', headerPrefix: '#'},

9 {methodName: 'h2', headerPrefix: '##'},

10 {methodName: 'h3', headerPrefix: '###'}

11 ]

12

13 var markdownHeader = {}

14 for (var i = 0; i < headerFns.length; i++) {

15 var fn = headerFns[i]

16 markdownHeader[fn.methodName] = markdownHeaderFn(fn)

Page 92: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 87

17 }

18

19 console.log(markdownHeader.h1('One'))

20 console.log(markdownHeader.h2('Two'))

21 console.log(markdownHeader.h3('Three'))

7.5 Exercises

Array to Map

In previous chapter, we requested you to write a function with such signature ar-

rayToMap(array, keyProperty, valueProperty) to convert an array to object map. Pleaserewrite it with such signature arrayToMap(array, iteratee). Object keys are the results ofrunning each element of array through iteratee. The corresponding value of each key isthe last element generated that key. The iteratee is invoked with three arguments, value,index, array.

Trampoline

What is Trampoline3?

a trampoline is a loop that iteratively invokes thunk-returning functions(continuation-passing style).�Programmers can use trampolined functions to implement tail-recursivefunction calls in stack-oriented programming languages.

The simplest form of trampoline is like below:

1 function trampoline(fn) {

2 var op = fn;

3 while (op != null && typeof op === 'function') {

4 op = op();

5 }

6 }

What is its usage? Remember in chapter 4, section Call Stack, if we pass a very largenumber to recursion function to calculate Factorial number, stack overflow error occurs.With Trampoline, we can eliminate such error.

Please fill in the logic for thunkedFactorial so that below code snippet works.

3https://en.wikipedia.org/wiki/Trampoline_

Page 93: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 88

1 // For reference

2 function factorial(n) {

3 return n === 0 ? 1 : n * factorial(n - 1);

4 }

5

6 function thunkedFactorial(n, cb) {

7 // Fill in the actual code here.

8 }

9

10 trampoline(thunkedFactorial.bind(this, 10, console.log.bind(console)))

11 // => 3628800

12

13 trampoline(thunkedFactorial.bind(this, 1000000, console.log.bind(console)))

14 // => Infinity

Notes: As the trampoline function detects return value of op for terminal condition, wehave to rewrite the factorial to accept a function cb to get the result instead of directlyreturning it.

Hints: bind, Partial Application

Currying

Notes: this is a bonus exercise. Don’t feel bad if you cannot work it out as it’s really reallyhard. Just want you to know how amazing JavaScript and functional programming canbe.

From wiki4:

currying is the technique of translating the evaluation of a function that takesmultiple arguments (or a tuple of arguments) into evaluating a sequence offunctions, each with a single argument.

Currying and partial function application are often conflated. One of thesignificant differences between the two is that a call to a partially appliedfunction returns the result right away, not another function down the curryingchain; this distinction can be illustrated clearly for functions whose arity isgreater than two.

4https://en.wikipedia.org/wiki/Currying

Page 94: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 89

1 // Original function

2 function addThreeNumber(a, b, c) {

3 return a + b + c

4 }

5

6 // Magic curry function

7 function curry3(fun){

8 return function(one){

9 return function(two){

10 return function (three){

11 return fun(one, two, three)

12 }

13 }

14 }

15 }

16

17 // Usage

18 var addThreeNumberCurried = curry3(addThreeNumber)

19 console.log(addThreeNumber(1, 2, 3))

20 console.log(addThreeNumberCurried(1)(2)(3))

The exercise here is that can you write a curryN function which works on functions withany number of arguments?

1 // Original functions

2 function addThreeNumber(a, b, c) {

3 return a + b + c

4 }

5 function mirror(input) {

6 return input

7 }

8 function random() {

9 return Math.random()

10 }

11

12 // Magic curryN function

13 function curryN(fn, n) {

14 // Fill in your code here

15 }

16

17 // Usage

18 var addThreeNumberCurried = curryN(addThreeNumber)

Page 95: KenChensamples.leanpub.com/tasting-javascript-sample.pdf · DataTypes 7 2.2SpecialNumbers ThecomputerweareusinghassuchhugememoryandfastCPUnow.Haveyouever wonderhowfastitcalculatesandwhatisthemaximumnumbersupportedinJavaScript?

Functional Programming 90

19 console.log(addThreeNumber(1, 2, 3))

20 console.log(addThreeNumberCurried(1)(2)(3))

21

22 var mirrorCurried = curryN(mirror)

23 console.log(mirror('Fantastic'))

24 console.log(mirrorCurried('Fantastic'))

25

26 var randomCurried = curryN(random)

27 console.log(random())

28 console.log(randomCurried())

Hints: bind, Partial Application, fn.length gives arguments number of a function