Practical JavaScript Programming Session 3 Wilson Su
2 https://www.slideshare.net/sweekson/
Outline 3 Practical JavaScript Programming Chapter 5. ● Function Definitions ● Function Parameters ● The Arguments Object ● What is ‘this’? ● Function Invocation ● Closures Functions Chapter 6. Constructors And Prototypes ● Constructors ● Prototypes ● Inheritance ● Class
4 Wilson Su Front-end Developer, HIE ● 6 years in web design ● Specialize in JavaScript / CSS / HTML / OOP / Git ● Familiar with PHP / Design Pattern ● Interested in UI & Ix Design wilson_su@trend.com.tw
Auxiliary Materials 5
Parentheses 6 1. 5.toString(); // SyntaxError 2. (5).toString(); // '5' 3. 4. var good = { grade: 'A' }, bad = { grade: 'F' }; 5. var score = 75; 6. 7. if (score > 60) { 8. good.grade; // 'A' 9. } else { 10. bad.grade; 11. } 12. 13. (score > 60 ? good : bad).grade; // 'A'
Chapter 5. Functions 7
In JavaScript, functions are first-class objects. 8
Function Definitions 9
3 Ways To Define A Function 10 1. /* Function declarations */ 2. function name ([param[, param[..., param]]]) { 3. [statements] 4. } 5. 6. /* Function expressions */ 7. var name = function [name] ([param[, param[..., param]]]) { 8. [statements] 9. } 10. 11. /* Function Constructor */ 12. var name = new Function([param[, param[..., param]],] body);
Function Declarations 11 1. function echo (value) { return value; } 2. typeof echo; // 'function' 3. echo.name; // 'echo' 4. echo.length; // 1 5. echo('ABC'); // 'ABC' 6. 7. function () {} // SyntaxError
Function Expressions 12 1. var multiply = function (x, y) { 2. return x * y; 3. }; 4. 5. typeof multiply; // 'function' 6. multiply.name; // 'multiply' 7. multiply.length; // 2 8. multiply(2, 3); // 6 9. 10. (function (value) { return value; }) 11. // function (value) { return value; }
Named Function Expressions 13 1. var calcalate = function calc (v1, v2) { 2. console.log(typeof calc); // 'function' 3. console.log(calcalate === calc); // true 4. return v1 + v2; 5. } 6. 7. typeof calcalate; // 'function' 8. calcalate.name; // 'calc' 9. calcalate.length; // 2 10. calcalate(2, 3); // 5 11. calc; // ? 1. var calcalate = function calc (v1, v2) { 2. console.log(typeof calc); // 'function' 3. console.log(calcalate === calc); // true 4. return v1 + v2; 5. } 6. 7. typeof calcalate; // 'function' 8. calcalate.name; // 'calc' 9. calcalate.length; // 2 10. calcalate(2, 3); // 5 11. calc; // ReferenceError
The Function() Constructor 14 1. var subtract = new Function('x', 'y', 'return x - y'); 2. 3. typeof subtract; // 'function' 4. subtract.name; // 'anonymous' 5. subtract.length; // 2 6. subtract(18, 3); // 15
Functions created with the Function constructor always are created in the global scope. 15
The Function() Constructor Create Functions In The Global Scope 16 1. var uppercaser = function (skill) { 2. return new Function('return skill.toUpperCase()'); 3. }; 4. var uppercase = uppercaser('html'); 5. var skill = 'css'; 6. 7. uppercase('js'); // ? 1. var uppercaser = function (skill) { 2. return new Function('return skill.toUpperCase()'); 3. }; 4. var uppercase = uppercaser('html'); 5. var skill = 'css'; 6. 7. uppercase('js'); // 'CSS'
Defining Object Methods 17 1. var dog = { 2. bark: function bowwow () { 3. console.log('Bowwow!'); 4. } 5. }; 6. 7. typeof dog.bark; // 'function' 8. dog.bark.name; // 'bowwow' 9. dog.bark.length; // 0 10. dog.bark(); // 'Bowwow!'
Defining Object Methods In A Shorter Syntax 18 1. var cat = { 2. meow () { 3. console.log('Meow~'); 4. } 5. }; 6. 7. typeof cat.meow; // 'function' 8. cat.meow.name; // 'meow' 9. cat.meow.length; // 0 10. cat.meow(); // 'Meow~'
Function Return 19 1. function noop () {} 2. function nothing () { return; } 3. function echo (value) { return value; } 4. 5. noop(true); // undefined 6. nothing('Hi'); // undefined 7. echo([10, 20]); // (2) [10, 20]
Function Hoisting 20 1. hello(); // 'Hello!' 2. aloha(); // ? 3. 4. function hello () { 5. return 'Hello!'; 6. } 7. 8. var aloha = function () { 9. return 'Aloha!'; 10. }; 1. hello(); // 'Hello!' 2. aloha(); // TypeError 3. 4. function hello () { 5. return 'Hello!'; 6. } 7. 8. var aloha = function () { 9. return 'Aloha!'; 10. };
Nested Functions 21 1. function outer () { 2. function inner () { 3. return 'Inner'; 4. } 5. return inner(); 6. } 7. 8. outer(); // 'Inner'; 9. inner(); // ? 1. function outer () { 2. function inner () { 3. return 'Inner'; 4. } 5. return inner(); 6. } 7. 8. outer(); // 'Inner'; 9. inner(); // ReferenceError
Arrow Functions 22 1. var remove = (target, array) => { 2. var index = array.indexOf(target); 3. return index > -1 ? !!array.splice(index, 1) : false; 4. }; 5. var concat = (list1, list2) => list1.concat(list2); 6. var numbers = [100, 200, 300]; 7. 8. remove(200, numbers); // true 9. numbers; // (2) [100, 300] 10. concat(numbers, [500, 700]); // (4) [100, 300, 500, 700] 11. numbers; // ? 1. var remove = (target, array) => { 2. var index = array.indexOf(target); 3. return index > -1 ? !!array.splice(index, 1) : false; 4. }; 5. var concat = (list1, list2) => list1.concat(list2); 6. var numbers = [100, 200, 300]; 7. 8. remove(200, numbers); // true 9. numbers; // (2) [100, 300] 10. concat(numbers, [500, 700]); // (4) [100, 300, 500, 700] 11. numbers; // (2) [100, 300]
More Examples With Arrow Functions 23 1. var noop = () => {}; 2. var book = title => ({ title }); 3. 4. book('Zero to One'); // {title: 'Zero to One'} 5. 6. [{ id: 10 }, { id: 20 }, { id: 30 }].map(item => item.id); 7. // (3) [10, 20, 30]
Generator Functions 24 1. function* generator (x) { 2. yield x * 10; 3. yield x + 50; 4. } 5. 6. var iterator = generator(10); 7. 8. typeof generator; // 'function' 9. typeof iterator; // 'object' 10. 11. iterator.next(); // {value: 100, done: false} 12. iterator.next(); // {value: 60, done: false} 13. iterator.next(); // {value: undefined, done: true}
Function Parameters 25
Parameter Defaults 26 1. function add (x, y) { 2. console.log(x); // 5 3. console.log(y); // undefined 4. console.log(x + y); // NaN 5. x = x || 0; 6. y = y || 0; 7. return x + y; 8. } 9. 10. add(5); // 5
Passed By Value / Passed By Reference 27 1. function update (string, object, array) { 2. string = 'aloha'; 3. object.id = 2; 4. array = []; 5. } 6. 7. var string = 'hello', object = { id: 1 }, array = [10, 20]; 8. 9. update(string, object, array); 10. console.log(string); // ? 11. console.log(object); // ? 12. console.log(array); // ? 1. function update (string, object, array) { 2. string = 'aloha'; 3. object.id = 2; 4. array = []; 5. } 6. 7. var string = 'hello', object = { id: 1 }, array = [10, 20]; 8. 9. update(string, object, array); 10. console.log(string); // 'hello' 11. console.log(object); // ? 12. console.log(array); // ? 1. function update (string, object, array) { 2. string = 'aloha'; 3. object.id = 2; 4. array = []; 5. } 6. 7. var string = 'hello', object = { id: 1 }, array = [10, 20]; 8. 9. update(string, object, array); 10. console.log(string); // 'hello' 11. console.log(object); // {id: 2} 12. console.log(array); // ? 1. function update (string, object, array) { 2. string = 'aloha'; 3. object.id = 2; 4. array = []; 5. } 6. 7. var string = 'hello', object = { id: 1 }, array = [10, 20]; 8. 9. update(string, object, array); 10. console.log(string); // 'hello' 11. console.log(object); // {id: 2} 12. console.log(array); // (2) [10, 20]
Default And Destructured Parameters 28 1. function fn1 (x = 0) {} 2. 3. function fn2 (x = y(), z = []) {} 4. 5. function fn3 (x, y = x, z = y + 1) {} 6. 7. function fn4 ({ multiplier = 3 }, [x, y, z = 5]) {}
Rest Parameters 29 1. function join (...args) { 2. return args.join(' '); 3. } 4. function sum (...[x, y, z]) { 5. return x + y + z; 6. } 7. 8. join('Ryan', 'likes', 'JS'); // 'Ryan likes JS' 9. 10. sum(1); // NaN 11. sum(1, 2, 3); // 6 12. sum(1, 2, 3, 4); // 6
The Arguments Object 30
The arguments Object 31 1. function fn () { 2. console.log(arguments); 3. } 4. 5. fn(10, 20); // (2) [10, 20]
The arguments object is not a real array. 32
The arguments Object 33 1. function fn () { 2. console.log(arguments.length); // 2 3. console.log(arguments[0]); // 10 4. console.log(arguments[1]); // 20 5. console.log(typeof arguments); // 'object' 6. console.log(arguments instanceof Array); // false 7. } 8. 9. fn(10, 20);
From arguments To An Array 34 1. function toArray1 () { 2. return Array.prototype.slice.call(arguments, 0); 3. } 4. function toArray2 () { 5. return [].slice.call(arguments, 0); 6. } 7. 8. toArray1(1, 2, 3); // (3) [1, 2, 3] 9. toArray1(1, 2, 3) instanceof Array; // true 10. 11. toArray2(4, 5, 6); // (3) [4, 5, 6] 12. toArray2(4, 5, 6) instanceof Array; // true
From arguments To An Array 35 1. function toArray3 () { 2. return arguments.length === 1 3. ? [arguments[0]] 4. : Array.apply(null, arguments); 5. } 6. 7. /* ES6 */ 8. function toArray4 () { 9. return Array.from(arguments); 10. }
Destructuring 36 1. function fn () { 2. var args = [...arguments]; 3. var [x, y, ...rest] = arguments; 4. 5. console.log(args); // (5) [10, 20, 30, 40, 50] 6. console.log(args instanceof Array); // true 7. console.log(x); // 10 8. console.log(y); // 20 9. console.log(rest); // (3) [30, 40, 50] 10. } 11. 12. fn(10, 20, 30, 40, 50);
Arrow funtions do not bind an arguments object. 37
Arrow Funtions 38 1. var fn = () => arguments; 2. var calc = function () { 3. var fn = (multiple) => arguments[0] * multiple; 4. return fn(3); 5. }; 6. 7. fn(); // ? 8. calc(8); // ? 1. var fn = () => arguments; 2. var calc = function () { 3. var fn = (multiple) => arguments[0] * multiple; 4. return fn(3); 5. }; 6. 7. fn(); // ReferenceError 8. calc(8); // ? 1. var fn = () => arguments; 2. var calc = function () { 3. var fn = (multiple) => arguments[0] * multiple; 4. return fn(3); 5. }; 6. 7. fn(); // ReferenceError 8. calc(8); // 24
What is ‘this’? 39
Global Context 40 1. /* In a browser */ 2. this; // Window { … } 3. this === window; // true 4. 5. /* In Node */ 6. this; // {} 7. this === module.exports; // true
Function Context 41 1. /* In a browser */ 2. var that = function () { return this; }; 3. that(); // Window { … } 4. that() === window; // true 5. 6. /* In Node */ 7. var that = function () { return this; }; 8. that(); // { global: …, console: … } 9. that() === global; // true
Nested Functions 42 1. var root = this; 2. function outer () { 3. function inner () { return this; } 4. var that = inner(); 5. 6. console.log(that); // Window { … } 7. console.log(that === window); // true 8. console.log(that === this); // true 9. console.log(that === root); // true 10. } 11. 12. outer();
The Function Constructor 43 1. var self = new Function('return this'); 2. 3. self(); // Window { … } 4. self() === window; // true 5. self() === this; // true
Object Methods 44 1. var data = { 2. self: function () { 3. return this; 4. } 5. }; 6. 7. data.self(); // {self: function} 8. data.self() === data; // true
Object Methods Refer To Global Functions 45 1. function age () { return this._age; } 2. 3. var dog = { _age: 5, age: age }; 4. var cat = { _age: 1, age: age }; 5. 6. dog.age(); // 5 7. cat.age(); // 1
Getters And Setters 46 1. var data = { 2. x: 10, 3. get y () { return this.x + 5; }, 4. set z (z) { this.x = this.x * z; } 5. }; 6. 7. data.z = 3; 8. 9. console.log(data.x); // ? 10. console.log(data.y); // ? 1. var data = { 2. x: 10, 3. get y () { return this.x + 5; }, 4. set z (z) { this.x = this.x * z; } 5. }; 6. 7. data.z = 3; 8. 9. console.log(data.x); // 30 10. console.log(data.y); // ? 1. var data = { 2. x: 10, 3. get y () { return this.x + 5; }, 4. set z (z) { this.x = this.x * z; } 5. }; 6. 7. data.z = 3; 8. 9. console.log(data.x); // 30 10. console.log(data.y); // 35
Method Chaining 47 1. [2, 5, 1, 7, 4] 2. .sort(function (a, b) { return a - b }) 3. .reverse() 4. .map(function (n) { return n * 10; }); 5. 6. // (6) [70, 50, 40, 20, 10]
Chainable Methods 48 1. var list = { 2. items: [3, 8, 5], 3. push: function (value) { 4. this.items.push(value); return this; 5. }, 6. remove: function (value) { 7. var index = this.items.indexOf(value); 8. if (index > -1) { this.items.splice(index, 1); } 9. return this; 10. } 11. }; 12. list.push(7).push(2).remove(8).items; 13. // (4) [3, 5, 7, 2]
An arrow function does not create its own this value. 49
Arrow Functions Used As Methods 50 1. var root = this; 2. var object = { 3. origin: function () { return this; }, 4. short: () => this 5. }; 6. 7. object.origin() === object; // true 8. object.origin() === object.short(); // false 9. object.short() === root; // true
Common Mistake With this 51 1. var zack = { 2. nickname: 'Z', 3. greet: function () { 4. console.log('Hi, I’m ' + this.nickname); 5. } 6. }; 7. var greet = zack.greet; 8. 9. greet(); // ? 1. var zack = { 2. nickname: 'Z', 3. greet: function () { 4. console.log('Hi, I’m ' + this.nickname); 5. } 6. }; 7. var greet = zack.greet; 8. 9. greet(); // 'Hi, I’m undefined'
Function Invocation 52
Invoking Functions 53 1. function add (x, y) { 2. return x + y; 3. } 4. 5. add(5, 8); // 13 6. Math.floor(3.14); // 3
Invoking Object Methods 54 1. var employee = { 2. title: 'PM', 3. name: 'Alex', 4. info: function () { 5. return this.name + ' is a ' + this.title; 6. } 7. }; 8. 9. employee.info(); // 'Alex is a PM'
Function Call 55 1. var name = 'Window'; 2. var jack = { name: 'Jack' }, nick = { name: 'Nick' }; 3. 4. function whoami () { return this.name; } 5. 6. whoami(); // 'Window' 7. whoami.call(this); // 'Window' 8. whoami.call(jack); // 'Jack' 9. whoami.call(nick); // 'Nick' 10. 11. [1, 2].concat.call([3, 4], [5, 6]); // ? 1. var name = 'Window'; 2. var jack = { name: 'Jack' }, nick = { name: 'Nick' }; 3. 4. function whoami () { return this.name; } 5. 6. whoami(); // 'Window' 7. whoami.call(this); // 'Window' 8. whoami.call(jack); // 'Jack' 9. whoami.call(nick); // 'Nick' 10. 11. [1, 2].concat.call([3, 4], [5, 6]); // (4) [3, 4, 5, 6]
Function Apply 56 1. Math.max(5, 2, 7, 4); // 7 2. Math.max.apply(null, [9, 1, 3, 6]); // 9 3. 4. function sum () { 5. return [].slice.call(arguments, 0).reduce((a, b) => a + b); 6. } 7. 8. sum.apply(null, [1, 2, 3, 4, 5]); // 15
The function.bind() Method 57 1. function color () { return this.color; } 2. 3. var yellow = { color: '#ff3' }; 4. var purple = { color: '#609' }; 5. 6. typeof color.bind(yellow); // 'function' 7. color.bind(yellow)(); // '#ff3' 8. 9. typeof color.bind(purple); // 'function' 10. color.bind(purple)(); // '#609'
Currying 58 1. function add (x, y) { 2. return x + y; 3. } 4. 5. var add5 = add.bind(null, 5); // Curried 6. 7. add(5, 3); // 8 8. 9. add5(10); // ? 10. add5(60); // ? 1. function add (x, y) { 2. return x + y; 3. } 4. 5. var add5 = add.bind(null, 5); // Curried 6. 7. add(5, 3); // 8 8. 9. add5(10); // 15 10. add5(60); // ? 1. function add (x, y) { 2. return x + y; 3. } 4. 5. var add5 = add.bind(null, 5); // Curried 6. 7. add(5, 3); // 8 8. 9. add5(10); // 15 10. add5(60); // 65
Self-Invoking Functions (Immediately Invoked Function Expression) 59 1. var number = (function (x) { return x + 3; })(7); 2. console.log(number); // 10 3. 4. (() => 'blabla')(); // 'blabla' 5. 6. (function (_) { 7. var title = 'My Home'; 8. console.log(window.title); // undefined 9. })(underscore);
Closures 60
A closure is the combination of a function and the lexical environment within which that function was declared. 61
Lexical Scope / Static Scope 62 1. function outer () { 2. var skill = 'JavaScript'; 3. function inner () { 4. console.log(skill); // 'JavaScript' 5. } 6. inner(); 7. console.log(title); // 'Tutorial' 8. } 9. var title = 'Tutorial'; 10. 11. outer();
inner() outer() global console.log(skill); console.log(title); (NONE) skill = 'JavaScript' title = 'Tutorial' Scope Chain 63 Closures ScopeChain Reference to outer lexical enviroment
Closures 64 1. function doubler (n) { return function () { return n * 2; }; } 2. function subtractor (x) { return (y) => (x = x - y); }; 3. 4. var sixteen = doubler(8); 5. var subtract = subtractor(100); 6. 7. sixteen(); // 16 8. 9. subtract(15); // ? 10. subtract(20); // ? 1. function doubler (n) { return function () { return n * 2; }; } 2. function subtractor (x) { return (y) => (x = x - y); }; 3. 4. var sixteen = doubler(8); 5. var subtract = subtractor(100); 6. 7. sixteen(); // 16 8. 9. subtract(15); // 85 10. subtract(20); // ? 1. function doubler (n) { return function () { return n * 2; }; } 2. function subtractor (x) { return (y) => (x = x - y); }; 3. 4. var sixteen = doubler(8); 5. var subtract = subtractor(100); 6. 7. sixteen(); // 16 8. 9. subtract(15); // 85 10. subtract(20); // 65
1. function doubler (n) { 2. return function () { 3. return n * 2; 4. }; 5. } 6. var sixteen = doubler(8); 65 Closure The instance sixteen maintains a reference to its lexical environment, within which the variable n exists.
Using Closure To Define Private Properties 66 1. function Circle (radius) { 2. this.getRadius = function () { return radius; }; 3. this.setRadius = function (value) { radius = value; }; 4. } 5. var circle = new Circle(10); 6. 7. circle.radius; // undefined 8. circle.getRadius(); // 10 9. circle.setRadius(20); // 20 10. circle.getRadius(); // 20
A Common Mistake With Closure 67 1. var i = 0, fn = {}; 2. 3. for (; i < 5; ++i) { 4. fn['get' + i] = function () { 5. console.log(i); 6. }; 7. } 8. 9. fn.get2(); // ? 1. var i = 0, fn = {}; 2. 3. for (; i < 5; ++i) { 4. fn['get' + i] = function () { 5. console.log(i); 6. }; 7. } 8. 9. fn.get2(); // 5
Chapter 6. Constructors And Prototypes 68
Constructors 69
Constructors 70 1. function Fruit (name) { 2. this.name = name; 3. } 4. 5. var kiwi = new Fruit('Kiwi'); 6. 7. kiwi.name; // 'Kiwi'
Arrow functions cannot be used as constructors. 71
Arrow Functions Cannot Be Used As Constructors 72 1. var Cloth = (type) => { 2. this.type = type; 3. }; 4. 5. new Cloth('Shirt'); // TypeError
Prototypes 73
Prototype-based Programming Prototype-based programming is a style of object-oriented programming in which behaviour reuse is performed via a process of reusing existing objects via delegation that serve as prototypes. – Wiki 74 Prototypes
The Special Object Properties 75 ● object.prototype returns a reference to the prototype for a class of objects. ● object.__proto__ returns a reference to the internal prototype of the specified object. Prototypes
The Prototype Chain Of An Instance 76 1. function Fruit (name) { 2. this.name = name; 3. } 4. 5. var kiwi = new Fruit(); 6. 7. kiwi.__proto__ === Fruit.prototype; // true 8. kiwi.__proto__.__proto__ === Object.prototype; // true 9. kiwi.__proto__.__proto__.__proto__; // * null 10. 11. kiwi.__proto__ === Object.getPrototypeOf(kiwi); // true
77 var kiwi = new Object(); kiwi.__proto__ = Fruit.prototype; Fruit.call(kiwi); 1 2 3 What Does The new Operator Do? Prototypes var kiwi = new Fruit(); ⇒ return kiwi;4
The Prototype Chain Of A Constructor 78 1. function Dog () {} 2. Dog.prototype.self = function () { return this; }; 3. 4. var dog = new Dog(); 5. 6. Dog.__proto__ === Function.prototype; // true 7. Dog.__proto__.__proto__ === Object.prototype; // true 8. Dog.__proto__.__proto__.__proto__; // * null 9. 10. Dog.prototype.constructor === Dog; // true 11. dog.constructor === Dog; // true
FunctionsInstances Prototypes d1 function Function () {} function Object () {} function Dog () {} Function.prototype Object.prototype Dog.prototype var … = new Dog(); d2 o1 var … = new Object(); o2 __proto__ prototype constructor null
Creating Objects Using Object.create() 80 1. var animal = { gender: 'Unknown' }; 2. var human = Object.create(animal); 3. var female = Object.create(human, { 4. gender: { value: 'Female' } 5. }); 6. 7. human.gender; // 'Unknown' 8. human.__proto__ === animal; // true 9. 10. female.gender; // 'Female' 11. female.__proto__ === human; // true 12. female.__proto__.__proto__ === animal; // true
Creating Objects Using Object.create(null) 81 1. var common = {}; 2. var uncommon = Object.create(null); 3. 4. common.constructor === Object; // true 5. common.__proto__ === Object.prototype; // true 6. 7. uncommon.constructor; // undefined 8. uncommon.__proto__; // undefined
You can add properties and methods to the prototype of built-in objects. 82
Adding Methods To Array.prototype 83 1. Array.prototype.first = function () { 2. return this[0]; 3. }; 4. 5. Array.prototype.last = function () { 6. return this[this.length - 1]; 7. }; 8. 9. var numbers = [100, 200, 300]; 10. 11. numbers.first(); // 100 12. numbers.last(); // 300
Avoid modifying the prototypes of standard JavaScript objects. 84
All built-in objects have a prototype property that is read-only. 85
Unconfigurable Object Prototypes 86 1. Array.prototype = { 2. first: function () { 3. return this[0]; 4. } 5. }; 6. 7. var numbers = [100, 200, 300]; 8. 9. numbers.first; // undefined 10. Object.getOwnPropertyDescriptor(Array, 'prototype'); 11. // {configurable: false, … }
Arrow functions do not have a prototype property. 87
Arrow Functions Do Not Have A prototype Pproperty 88 1. var Cloth = (type) => { 2. this.type = type; 3. }; 4. 5. Cloth.prototype; // undefined
Inheritance 89
All objects inherit their properties and methods from their prototype. 90
Native Prototypes 91 1. (10).toFixed === Number.prototype.toFixed; // true 2. (true).valueOf === Boolean.prototype.valueOf; // true 3. ('A').trim === String.prototype.trim; // true 4. ({}).toString === Object.prototype.toString; // true 5. ([]).concat === Array.prototype.concat; // true
Overriding The Native Prototypes 92 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // ? 7. 'Java' + script; // ? 8. Number(empty); // NaN 9. Number(ten); // ? 10. ten + 20; // ? 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // 'Script' 7. 'Java' + script; // ? 8. Number(empty); // NaN 9. Number(ten); // ? 10. ten + 20; // ? 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // 'Script' 7. 'Java' + script; // 'JavaScript' 8. Number(empty); // NaN 9. Number(ten); // ? 10. ten + 20; // ? 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // 'Script' 7. 'Java' + script; // 'JavaScript' 8. Number(empty); // NaN 9. Number(ten); // 10 10. ten + 20; // ? 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // 'Script' 7. 'Java' + script; // 'JavaScript' 8. Number(empty); // NaN 9. Number(ten); // 10 10. ten + 20; // 30
A Custom Object 93 1. function Pig (name) { this.name = name; } 2. Pig.prototype.type = 'Pig'; 3. Pig.prototype.sleep = function () { console.log('zZzZ…'); }; 4. 5. var piggy = new Pig('Wilbur'); 6. 7. piggy.name; // 'Wilbur' 8. piggy.type; // 'Pig' 9. piggy.sleep(); // 'zZzZ…'; 10. piggy instanceof Pig; // true 11. piggy instanceof Object; // true
Shared Properties 94 1. function Player () { this.counting(); } 2. Player.prototype.counter = { value: 0 }; 3. Player.prototype.counting = function () { 4. ++this.counter.value; 5. }; 6. 7. var player1 = new Player(); 8. player1.counter.value; // 1 9. 10. var player2 = new Player(); 11. player2.counter.value; // 2 12. player1.counter.value; // 2
It is recommended to define methods to all instances through object prototype. 95
Instance Properties And Prototype Properties 96 1. function Robot () { 2. this.walk = function () {} 3. } 4. Robot.prototype.talk = function () {}; 5. 6. var wat = new Robot(), eve = new Robot(); 7. 8. wat.walk === eve.walk; // false 9. wat.talk === eve.talk; // true 10. wat.talk === Robot.prototype.talk; // true 11. wat.hasOwnProperty('walk'); // true 12. wat.hasOwnProperty('talk'); // false
Classical Inheritance With Object.create() 97 1. function Bird () {} 2. Bird.prototype.fly = function () {}; 3. 4. function Pigeon () { Bird.call(this); } 5. Pigeon.prototype = Object.create(Bird.prototype); 6. Pigeon.prototype.constructor = Pigeon; 7. var pigeon = new Pigeon(); 8. 9. Pigeon.prototype.__proto__ === Bird.prototype; // true 10. pigeon.fly === Pigeon.prototype.fly; // true 11. pigeon.fly === Bird.prototype.fly; // true
Override Methods 98 1. function Bird () {} 2. Bird.prototype.fly = function () { return 'Default'; }; 3. 4. function Eagle () { Bird.call(this); } 5. Eagle.prototype = Object.create(Bird.prototype); 6. Eagle.prototype.constructor = Eagle; 7. Eagle.prototype.fly = function () { return 'Overrode'; }; 8. var eagle = new Eagle(); 9. 10. Eagle.prototype.__proto__ === Bird.prototype; // true 11. eagle.fly === Eagle.prototype.fly; // true 12. eagle.fly === Bird.prototype.fly; // false
Class 99
Class Declarations 100 1. class Bird { 2. constructor (type) { 3. this.type = type; 4. } 5. fly () { 6. console.log('Fly!'); 7. } 8. } 9. 10. typeof Bird; // 'function'
Sub Classing With extends 101 1. class Penguin extends Bird { 2. constructor () { 3. super('Penguin'); 4. } 5. fly () { 6. super.fly(); 7. console.log('Penguin Fly!'); 8. } 9. } 10. 11. Penguin.prototype.fly === Bird.prototype.fly; // false
Static Methods 102 1. class Food { 2. static calorie () {} 3. } 4. 5. function Drink () {} 6. Drink.calorie = function () {}
The best thing about JavaScript is its implementation of functions. It got almost everything right. But, as you should expect with JavaScript, it didn't get everything right. - Douglas Crockford 103
Questions? 104
Reference 105 ● JavaScript | CodeData ● Prototype-based programming - Wikipedia ● First-class function - Wikipedia ● JavaScript Guide - JavaScript | MDN ● JavaScript Tutorial | W3Schools Practical JavaScript Programming
Reference Books ● JavaScript: The Good Parts ● Effective JavaScript 106 Practical JavaScript Programming
THANKS

Practical JavaScript Programming - Session 3/8

  • 1.
  • 2.
  • 3.
    Outline 3 Practical JavaScript Programming Chapter5. ● Function Definitions ● Function Parameters ● The Arguments Object ● What is ‘this’? ● Function Invocation ● Closures Functions Chapter 6. Constructors And Prototypes ● Constructors ● Prototypes ● Inheritance ● Class
  • 4.
    4 Wilson Su Front-end Developer,HIE ● 6 years in web design ● Specialize in JavaScript / CSS / HTML / OOP / Git ● Familiar with PHP / Design Pattern ● Interested in UI & Ix Design wilson_su@trend.com.tw
  • 5.
  • 6.
    Parentheses 6 1. 5.toString(); //SyntaxError 2. (5).toString(); // '5' 3. 4. var good = { grade: 'A' }, bad = { grade: 'F' }; 5. var score = 75; 6. 7. if (score > 60) { 8. good.grade; // 'A' 9. } else { 10. bad.grade; 11. } 12. 13. (score > 60 ? good : bad).grade; // 'A'
  • 7.
  • 8.
    In JavaScript, functionsare first-class objects. 8
  • 9.
  • 10.
    3 Ways ToDefine A Function 10 1. /* Function declarations */ 2. function name ([param[, param[..., param]]]) { 3. [statements] 4. } 5. 6. /* Function expressions */ 7. var name = function [name] ([param[, param[..., param]]]) { 8. [statements] 9. } 10. 11. /* Function Constructor */ 12. var name = new Function([param[, param[..., param]],] body);
  • 11.
    Function Declarations 11 1. functionecho (value) { return value; } 2. typeof echo; // 'function' 3. echo.name; // 'echo' 4. echo.length; // 1 5. echo('ABC'); // 'ABC' 6. 7. function () {} // SyntaxError
  • 12.
    Function Expressions 12 1. varmultiply = function (x, y) { 2. return x * y; 3. }; 4. 5. typeof multiply; // 'function' 6. multiply.name; // 'multiply' 7. multiply.length; // 2 8. multiply(2, 3); // 6 9. 10. (function (value) { return value; }) 11. // function (value) { return value; }
  • 13.
    Named Function Expressions 13 1.var calcalate = function calc (v1, v2) { 2. console.log(typeof calc); // 'function' 3. console.log(calcalate === calc); // true 4. return v1 + v2; 5. } 6. 7. typeof calcalate; // 'function' 8. calcalate.name; // 'calc' 9. calcalate.length; // 2 10. calcalate(2, 3); // 5 11. calc; // ? 1. var calcalate = function calc (v1, v2) { 2. console.log(typeof calc); // 'function' 3. console.log(calcalate === calc); // true 4. return v1 + v2; 5. } 6. 7. typeof calcalate; // 'function' 8. calcalate.name; // 'calc' 9. calcalate.length; // 2 10. calcalate(2, 3); // 5 11. calc; // ReferenceError
  • 14.
    The Function() Constructor 14 1.var subtract = new Function('x', 'y', 'return x - y'); 2. 3. typeof subtract; // 'function' 4. subtract.name; // 'anonymous' 5. subtract.length; // 2 6. subtract(18, 3); // 15
  • 15.
    Functions created with theFunction constructor always are created in the global scope. 15
  • 16.
    The Function() ConstructorCreate Functions In The Global Scope 16 1. var uppercaser = function (skill) { 2. return new Function('return skill.toUpperCase()'); 3. }; 4. var uppercase = uppercaser('html'); 5. var skill = 'css'; 6. 7. uppercase('js'); // ? 1. var uppercaser = function (skill) { 2. return new Function('return skill.toUpperCase()'); 3. }; 4. var uppercase = uppercaser('html'); 5. var skill = 'css'; 6. 7. uppercase('js'); // 'CSS'
  • 17.
    Defining Object Methods 17 1.var dog = { 2. bark: function bowwow () { 3. console.log('Bowwow!'); 4. } 5. }; 6. 7. typeof dog.bark; // 'function' 8. dog.bark.name; // 'bowwow' 9. dog.bark.length; // 0 10. dog.bark(); // 'Bowwow!'
  • 18.
    Defining Object MethodsIn A Shorter Syntax 18 1. var cat = { 2. meow () { 3. console.log('Meow~'); 4. } 5. }; 6. 7. typeof cat.meow; // 'function' 8. cat.meow.name; // 'meow' 9. cat.meow.length; // 0 10. cat.meow(); // 'Meow~'
  • 19.
    Function Return 19 1. functionnoop () {} 2. function nothing () { return; } 3. function echo (value) { return value; } 4. 5. noop(true); // undefined 6. nothing('Hi'); // undefined 7. echo([10, 20]); // (2) [10, 20]
  • 20.
    Function Hoisting 20 1. hello();// 'Hello!' 2. aloha(); // ? 3. 4. function hello () { 5. return 'Hello!'; 6. } 7. 8. var aloha = function () { 9. return 'Aloha!'; 10. }; 1. hello(); // 'Hello!' 2. aloha(); // TypeError 3. 4. function hello () { 5. return 'Hello!'; 6. } 7. 8. var aloha = function () { 9. return 'Aloha!'; 10. };
  • 21.
    Nested Functions 21 1. functionouter () { 2. function inner () { 3. return 'Inner'; 4. } 5. return inner(); 6. } 7. 8. outer(); // 'Inner'; 9. inner(); // ? 1. function outer () { 2. function inner () { 3. return 'Inner'; 4. } 5. return inner(); 6. } 7. 8. outer(); // 'Inner'; 9. inner(); // ReferenceError
  • 22.
    Arrow Functions 22 1. varremove = (target, array) => { 2. var index = array.indexOf(target); 3. return index > -1 ? !!array.splice(index, 1) : false; 4. }; 5. var concat = (list1, list2) => list1.concat(list2); 6. var numbers = [100, 200, 300]; 7. 8. remove(200, numbers); // true 9. numbers; // (2) [100, 300] 10. concat(numbers, [500, 700]); // (4) [100, 300, 500, 700] 11. numbers; // ? 1. var remove = (target, array) => { 2. var index = array.indexOf(target); 3. return index > -1 ? !!array.splice(index, 1) : false; 4. }; 5. var concat = (list1, list2) => list1.concat(list2); 6. var numbers = [100, 200, 300]; 7. 8. remove(200, numbers); // true 9. numbers; // (2) [100, 300] 10. concat(numbers, [500, 700]); // (4) [100, 300, 500, 700] 11. numbers; // (2) [100, 300]
  • 23.
    More Examples WithArrow Functions 23 1. var noop = () => {}; 2. var book = title => ({ title }); 3. 4. book('Zero to One'); // {title: 'Zero to One'} 5. 6. [{ id: 10 }, { id: 20 }, { id: 30 }].map(item => item.id); 7. // (3) [10, 20, 30]
  • 24.
    Generator Functions 24 1. function*generator (x) { 2. yield x * 10; 3. yield x + 50; 4. } 5. 6. var iterator = generator(10); 7. 8. typeof generator; // 'function' 9. typeof iterator; // 'object' 10. 11. iterator.next(); // {value: 100, done: false} 12. iterator.next(); // {value: 60, done: false} 13. iterator.next(); // {value: undefined, done: true}
  • 25.
  • 26.
    Parameter Defaults 26 1. functionadd (x, y) { 2. console.log(x); // 5 3. console.log(y); // undefined 4. console.log(x + y); // NaN 5. x = x || 0; 6. y = y || 0; 7. return x + y; 8. } 9. 10. add(5); // 5
  • 27.
    Passed By Value/ Passed By Reference 27 1. function update (string, object, array) { 2. string = 'aloha'; 3. object.id = 2; 4. array = []; 5. } 6. 7. var string = 'hello', object = { id: 1 }, array = [10, 20]; 8. 9. update(string, object, array); 10. console.log(string); // ? 11. console.log(object); // ? 12. console.log(array); // ? 1. function update (string, object, array) { 2. string = 'aloha'; 3. object.id = 2; 4. array = []; 5. } 6. 7. var string = 'hello', object = { id: 1 }, array = [10, 20]; 8. 9. update(string, object, array); 10. console.log(string); // 'hello' 11. console.log(object); // ? 12. console.log(array); // ? 1. function update (string, object, array) { 2. string = 'aloha'; 3. object.id = 2; 4. array = []; 5. } 6. 7. var string = 'hello', object = { id: 1 }, array = [10, 20]; 8. 9. update(string, object, array); 10. console.log(string); // 'hello' 11. console.log(object); // {id: 2} 12. console.log(array); // ? 1. function update (string, object, array) { 2. string = 'aloha'; 3. object.id = 2; 4. array = []; 5. } 6. 7. var string = 'hello', object = { id: 1 }, array = [10, 20]; 8. 9. update(string, object, array); 10. console.log(string); // 'hello' 11. console.log(object); // {id: 2} 12. console.log(array); // (2) [10, 20]
  • 28.
    Default And DestructuredParameters 28 1. function fn1 (x = 0) {} 2. 3. function fn2 (x = y(), z = []) {} 4. 5. function fn3 (x, y = x, z = y + 1) {} 6. 7. function fn4 ({ multiplier = 3 }, [x, y, z = 5]) {}
  • 29.
    Rest Parameters 29 1. functionjoin (...args) { 2. return args.join(' '); 3. } 4. function sum (...[x, y, z]) { 5. return x + y + z; 6. } 7. 8. join('Ryan', 'likes', 'JS'); // 'Ryan likes JS' 9. 10. sum(1); // NaN 11. sum(1, 2, 3); // 6 12. sum(1, 2, 3, 4); // 6
  • 30.
  • 31.
    The arguments Object 31 1.function fn () { 2. console.log(arguments); 3. } 4. 5. fn(10, 20); // (2) [10, 20]
  • 32.
    The arguments objectis not a real array. 32
  • 33.
    The arguments Object 33 1.function fn () { 2. console.log(arguments.length); // 2 3. console.log(arguments[0]); // 10 4. console.log(arguments[1]); // 20 5. console.log(typeof arguments); // 'object' 6. console.log(arguments instanceof Array); // false 7. } 8. 9. fn(10, 20);
  • 34.
    From arguments ToAn Array 34 1. function toArray1 () { 2. return Array.prototype.slice.call(arguments, 0); 3. } 4. function toArray2 () { 5. return [].slice.call(arguments, 0); 6. } 7. 8. toArray1(1, 2, 3); // (3) [1, 2, 3] 9. toArray1(1, 2, 3) instanceof Array; // true 10. 11. toArray2(4, 5, 6); // (3) [4, 5, 6] 12. toArray2(4, 5, 6) instanceof Array; // true
  • 35.
    From arguments ToAn Array 35 1. function toArray3 () { 2. return arguments.length === 1 3. ? [arguments[0]] 4. : Array.apply(null, arguments); 5. } 6. 7. /* ES6 */ 8. function toArray4 () { 9. return Array.from(arguments); 10. }
  • 36.
    Destructuring 36 1. function fn() { 2. var args = [...arguments]; 3. var [x, y, ...rest] = arguments; 4. 5. console.log(args); // (5) [10, 20, 30, 40, 50] 6. console.log(args instanceof Array); // true 7. console.log(x); // 10 8. console.log(y); // 20 9. console.log(rest); // (3) [30, 40, 50] 10. } 11. 12. fn(10, 20, 30, 40, 50);
  • 37.
    Arrow funtions donot bind an arguments object. 37
  • 38.
    Arrow Funtions 38 1. varfn = () => arguments; 2. var calc = function () { 3. var fn = (multiple) => arguments[0] * multiple; 4. return fn(3); 5. }; 6. 7. fn(); // ? 8. calc(8); // ? 1. var fn = () => arguments; 2. var calc = function () { 3. var fn = (multiple) => arguments[0] * multiple; 4. return fn(3); 5. }; 6. 7. fn(); // ReferenceError 8. calc(8); // ? 1. var fn = () => arguments; 2. var calc = function () { 3. var fn = (multiple) => arguments[0] * multiple; 4. return fn(3); 5. }; 6. 7. fn(); // ReferenceError 8. calc(8); // 24
  • 39.
  • 40.
    Global Context 40 1. /*In a browser */ 2. this; // Window { … } 3. this === window; // true 4. 5. /* In Node */ 6. this; // {} 7. this === module.exports; // true
  • 41.
    Function Context 41 1. /*In a browser */ 2. var that = function () { return this; }; 3. that(); // Window { … } 4. that() === window; // true 5. 6. /* In Node */ 7. var that = function () { return this; }; 8. that(); // { global: …, console: … } 9. that() === global; // true
  • 42.
    Nested Functions 42 1. varroot = this; 2. function outer () { 3. function inner () { return this; } 4. var that = inner(); 5. 6. console.log(that); // Window { … } 7. console.log(that === window); // true 8. console.log(that === this); // true 9. console.log(that === root); // true 10. } 11. 12. outer();
  • 43.
    The Function Constructor 43 1.var self = new Function('return this'); 2. 3. self(); // Window { … } 4. self() === window; // true 5. self() === this; // true
  • 44.
    Object Methods 44 1. vardata = { 2. self: function () { 3. return this; 4. } 5. }; 6. 7. data.self(); // {self: function} 8. data.self() === data; // true
  • 45.
    Object Methods ReferTo Global Functions 45 1. function age () { return this._age; } 2. 3. var dog = { _age: 5, age: age }; 4. var cat = { _age: 1, age: age }; 5. 6. dog.age(); // 5 7. cat.age(); // 1
  • 46.
    Getters And Setters 46 1.var data = { 2. x: 10, 3. get y () { return this.x + 5; }, 4. set z (z) { this.x = this.x * z; } 5. }; 6. 7. data.z = 3; 8. 9. console.log(data.x); // ? 10. console.log(data.y); // ? 1. var data = { 2. x: 10, 3. get y () { return this.x + 5; }, 4. set z (z) { this.x = this.x * z; } 5. }; 6. 7. data.z = 3; 8. 9. console.log(data.x); // 30 10. console.log(data.y); // ? 1. var data = { 2. x: 10, 3. get y () { return this.x + 5; }, 4. set z (z) { this.x = this.x * z; } 5. }; 6. 7. data.z = 3; 8. 9. console.log(data.x); // 30 10. console.log(data.y); // 35
  • 47.
    Method Chaining 47 1. [2,5, 1, 7, 4] 2. .sort(function (a, b) { return a - b }) 3. .reverse() 4. .map(function (n) { return n * 10; }); 5. 6. // (6) [70, 50, 40, 20, 10]
  • 48.
    Chainable Methods 48 1. varlist = { 2. items: [3, 8, 5], 3. push: function (value) { 4. this.items.push(value); return this; 5. }, 6. remove: function (value) { 7. var index = this.items.indexOf(value); 8. if (index > -1) { this.items.splice(index, 1); } 9. return this; 10. } 11. }; 12. list.push(7).push(2).remove(8).items; 13. // (4) [3, 5, 7, 2]
  • 49.
    An arrow functiondoes not create its own this value. 49
  • 50.
    Arrow Functions UsedAs Methods 50 1. var root = this; 2. var object = { 3. origin: function () { return this; }, 4. short: () => this 5. }; 6. 7. object.origin() === object; // true 8. object.origin() === object.short(); // false 9. object.short() === root; // true
  • 51.
    Common Mistake Withthis 51 1. var zack = { 2. nickname: 'Z', 3. greet: function () { 4. console.log('Hi, I’m ' + this.nickname); 5. } 6. }; 7. var greet = zack.greet; 8. 9. greet(); // ? 1. var zack = { 2. nickname: 'Z', 3. greet: function () { 4. console.log('Hi, I’m ' + this.nickname); 5. } 6. }; 7. var greet = zack.greet; 8. 9. greet(); // 'Hi, I’m undefined'
  • 52.
  • 53.
    Invoking Functions 53 1. functionadd (x, y) { 2. return x + y; 3. } 4. 5. add(5, 8); // 13 6. Math.floor(3.14); // 3
  • 54.
    Invoking Object Methods 54 1.var employee = { 2. title: 'PM', 3. name: 'Alex', 4. info: function () { 5. return this.name + ' is a ' + this.title; 6. } 7. }; 8. 9. employee.info(); // 'Alex is a PM'
  • 55.
    Function Call 55 1. varname = 'Window'; 2. var jack = { name: 'Jack' }, nick = { name: 'Nick' }; 3. 4. function whoami () { return this.name; } 5. 6. whoami(); // 'Window' 7. whoami.call(this); // 'Window' 8. whoami.call(jack); // 'Jack' 9. whoami.call(nick); // 'Nick' 10. 11. [1, 2].concat.call([3, 4], [5, 6]); // ? 1. var name = 'Window'; 2. var jack = { name: 'Jack' }, nick = { name: 'Nick' }; 3. 4. function whoami () { return this.name; } 5. 6. whoami(); // 'Window' 7. whoami.call(this); // 'Window' 8. whoami.call(jack); // 'Jack' 9. whoami.call(nick); // 'Nick' 10. 11. [1, 2].concat.call([3, 4], [5, 6]); // (4) [3, 4, 5, 6]
  • 56.
    Function Apply 56 1. Math.max(5,2, 7, 4); // 7 2. Math.max.apply(null, [9, 1, 3, 6]); // 9 3. 4. function sum () { 5. return [].slice.call(arguments, 0).reduce((a, b) => a + b); 6. } 7. 8. sum.apply(null, [1, 2, 3, 4, 5]); // 15
  • 57.
    The function.bind() Method 57 1.function color () { return this.color; } 2. 3. var yellow = { color: '#ff3' }; 4. var purple = { color: '#609' }; 5. 6. typeof color.bind(yellow); // 'function' 7. color.bind(yellow)(); // '#ff3' 8. 9. typeof color.bind(purple); // 'function' 10. color.bind(purple)(); // '#609'
  • 58.
    Currying 58 1. function add(x, y) { 2. return x + y; 3. } 4. 5. var add5 = add.bind(null, 5); // Curried 6. 7. add(5, 3); // 8 8. 9. add5(10); // ? 10. add5(60); // ? 1. function add (x, y) { 2. return x + y; 3. } 4. 5. var add5 = add.bind(null, 5); // Curried 6. 7. add(5, 3); // 8 8. 9. add5(10); // 15 10. add5(60); // ? 1. function add (x, y) { 2. return x + y; 3. } 4. 5. var add5 = add.bind(null, 5); // Curried 6. 7. add(5, 3); // 8 8. 9. add5(10); // 15 10. add5(60); // 65
  • 59.
    Self-Invoking Functions (ImmediatelyInvoked Function Expression) 59 1. var number = (function (x) { return x + 3; })(7); 2. console.log(number); // 10 3. 4. (() => 'blabla')(); // 'blabla' 5. 6. (function (_) { 7. var title = 'My Home'; 8. console.log(window.title); // undefined 9. })(underscore);
  • 60.
  • 61.
    A closure isthe combination of a function and the lexical environment within which that function was declared. 61
  • 62.
    Lexical Scope /Static Scope 62 1. function outer () { 2. var skill = 'JavaScript'; 3. function inner () { 4. console.log(skill); // 'JavaScript' 5. } 6. inner(); 7. console.log(title); // 'Tutorial' 8. } 9. var title = 'Tutorial'; 10. 11. outer();
  • 63.
    inner() outer() global console.log(skill); console.log(title); (NONE) skill = 'JavaScript' title= 'Tutorial' Scope Chain 63 Closures ScopeChain Reference to outer lexical enviroment
  • 64.
    Closures 64 1. function doubler(n) { return function () { return n * 2; }; } 2. function subtractor (x) { return (y) => (x = x - y); }; 3. 4. var sixteen = doubler(8); 5. var subtract = subtractor(100); 6. 7. sixteen(); // 16 8. 9. subtract(15); // ? 10. subtract(20); // ? 1. function doubler (n) { return function () { return n * 2; }; } 2. function subtractor (x) { return (y) => (x = x - y); }; 3. 4. var sixteen = doubler(8); 5. var subtract = subtractor(100); 6. 7. sixteen(); // 16 8. 9. subtract(15); // 85 10. subtract(20); // ? 1. function doubler (n) { return function () { return n * 2; }; } 2. function subtractor (x) { return (y) => (x = x - y); }; 3. 4. var sixteen = doubler(8); 5. var subtract = subtractor(100); 6. 7. sixteen(); // 16 8. 9. subtract(15); // 85 10. subtract(20); // 65
  • 65.
    1. function doubler(n) { 2. return function () { 3. return n * 2; 4. }; 5. } 6. var sixteen = doubler(8); 65 Closure The instance sixteen maintains a reference to its lexical environment, within which the variable n exists.
  • 66.
    Using Closure ToDefine Private Properties 66 1. function Circle (radius) { 2. this.getRadius = function () { return radius; }; 3. this.setRadius = function (value) { radius = value; }; 4. } 5. var circle = new Circle(10); 6. 7. circle.radius; // undefined 8. circle.getRadius(); // 10 9. circle.setRadius(20); // 20 10. circle.getRadius(); // 20
  • 67.
    A Common MistakeWith Closure 67 1. var i = 0, fn = {}; 2. 3. for (; i < 5; ++i) { 4. fn['get' + i] = function () { 5. console.log(i); 6. }; 7. } 8. 9. fn.get2(); // ? 1. var i = 0, fn = {}; 2. 3. for (; i < 5; ++i) { 4. fn['get' + i] = function () { 5. console.log(i); 6. }; 7. } 8. 9. fn.get2(); // 5
  • 68.
  • 69.
  • 70.
    Constructors 70 1. function Fruit(name) { 2. this.name = name; 3. } 4. 5. var kiwi = new Fruit('Kiwi'); 6. 7. kiwi.name; // 'Kiwi'
  • 71.
    Arrow functions cannot beused as constructors. 71
  • 72.
    Arrow Functions CannotBe Used As Constructors 72 1. var Cloth = (type) => { 2. this.type = type; 3. }; 4. 5. new Cloth('Shirt'); // TypeError
  • 73.
  • 74.
    Prototype-based Programming Prototype-based programmingis a style of object-oriented programming in which behaviour reuse is performed via a process of reusing existing objects via delegation that serve as prototypes. – Wiki 74 Prototypes
  • 75.
    The Special ObjectProperties 75 ● object.prototype returns a reference to the prototype for a class of objects. ● object.__proto__ returns a reference to the internal prototype of the specified object. Prototypes
  • 76.
    The Prototype ChainOf An Instance 76 1. function Fruit (name) { 2. this.name = name; 3. } 4. 5. var kiwi = new Fruit(); 6. 7. kiwi.__proto__ === Fruit.prototype; // true 8. kiwi.__proto__.__proto__ === Object.prototype; // true 9. kiwi.__proto__.__proto__.__proto__; // * null 10. 11. kiwi.__proto__ === Object.getPrototypeOf(kiwi); // true
  • 77.
    77 var kiwi =new Object(); kiwi.__proto__ = Fruit.prototype; Fruit.call(kiwi); 1 2 3 What Does The new Operator Do? Prototypes var kiwi = new Fruit(); ⇒ return kiwi;4
  • 78.
    The Prototype ChainOf A Constructor 78 1. function Dog () {} 2. Dog.prototype.self = function () { return this; }; 3. 4. var dog = new Dog(); 5. 6. Dog.__proto__ === Function.prototype; // true 7. Dog.__proto__.__proto__ === Object.prototype; // true 8. Dog.__proto__.__proto__.__proto__; // * null 9. 10. Dog.prototype.constructor === Dog; // true 11. dog.constructor === Dog; // true
  • 79.
    FunctionsInstances Prototypes d1 function Function() {} function Object () {} function Dog () {} Function.prototype Object.prototype Dog.prototype var … = new Dog(); d2 o1 var … = new Object(); o2 __proto__ prototype constructor null
  • 80.
    Creating Objects UsingObject.create() 80 1. var animal = { gender: 'Unknown' }; 2. var human = Object.create(animal); 3. var female = Object.create(human, { 4. gender: { value: 'Female' } 5. }); 6. 7. human.gender; // 'Unknown' 8. human.__proto__ === animal; // true 9. 10. female.gender; // 'Female' 11. female.__proto__ === human; // true 12. female.__proto__.__proto__ === animal; // true
  • 81.
    Creating Objects UsingObject.create(null) 81 1. var common = {}; 2. var uncommon = Object.create(null); 3. 4. common.constructor === Object; // true 5. common.__proto__ === Object.prototype; // true 6. 7. uncommon.constructor; // undefined 8. uncommon.__proto__; // undefined
  • 82.
    You can addproperties and methods to the prototype of built-in objects. 82
  • 83.
    Adding Methods ToArray.prototype 83 1. Array.prototype.first = function () { 2. return this[0]; 3. }; 4. 5. Array.prototype.last = function () { 6. return this[this.length - 1]; 7. }; 8. 9. var numbers = [100, 200, 300]; 10. 11. numbers.first(); // 100 12. numbers.last(); // 300
  • 84.
    Avoid modifying theprototypes of standard JavaScript objects. 84
  • 85.
    All built-in objects havea prototype property that is read-only. 85
  • 86.
    Unconfigurable Object Prototypes 86 1.Array.prototype = { 2. first: function () { 3. return this[0]; 4. } 5. }; 6. 7. var numbers = [100, 200, 300]; 8. 9. numbers.first; // undefined 10. Object.getOwnPropertyDescriptor(Array, 'prototype'); 11. // {configurable: false, … }
  • 87.
    Arrow functions donot have a prototype property. 87
  • 88.
    Arrow Functions DoNot Have A prototype Pproperty 88 1. var Cloth = (type) => { 2. this.type = type; 3. }; 4. 5. Cloth.prototype; // undefined
  • 89.
  • 90.
    All objects inherittheir properties and methods from their prototype. 90
  • 91.
    Native Prototypes 91 1. (10).toFixed=== Number.prototype.toFixed; // true 2. (true).valueOf === Boolean.prototype.valueOf; // true 3. ('A').trim === String.prototype.trim; // true 4. ({}).toString === Object.prototype.toString; // true 5. ([]).concat === Array.prototype.concat; // true
  • 92.
    Overriding The NativePrototypes 92 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // ? 7. 'Java' + script; // ? 8. Number(empty); // NaN 9. Number(ten); // ? 10. ten + 20; // ? 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // 'Script' 7. 'Java' + script; // ? 8. Number(empty); // NaN 9. Number(ten); // ? 10. ten + 20; // ? 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // 'Script' 7. 'Java' + script; // 'JavaScript' 8. Number(empty); // NaN 9. Number(ten); // ? 10. ten + 20; // ? 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // 'Script' 7. 'Java' + script; // 'JavaScript' 8. Number(empty); // NaN 9. Number(ten); // 10 10. ten + 20; // ? 1. var empty = {}; 2. var script = { toString: () => 'Script' }; 3. var ten = { valueOf: () => 10 }; 4. 5. String(empty); // '[object Object]' 6. String(script); // 'Script' 7. 'Java' + script; // 'JavaScript' 8. Number(empty); // NaN 9. Number(ten); // 10 10. ten + 20; // 30
  • 93.
    A Custom Object 93 1.function Pig (name) { this.name = name; } 2. Pig.prototype.type = 'Pig'; 3. Pig.prototype.sleep = function () { console.log('zZzZ…'); }; 4. 5. var piggy = new Pig('Wilbur'); 6. 7. piggy.name; // 'Wilbur' 8. piggy.type; // 'Pig' 9. piggy.sleep(); // 'zZzZ…'; 10. piggy instanceof Pig; // true 11. piggy instanceof Object; // true
  • 94.
    Shared Properties 94 1. functionPlayer () { this.counting(); } 2. Player.prototype.counter = { value: 0 }; 3. Player.prototype.counting = function () { 4. ++this.counter.value; 5. }; 6. 7. var player1 = new Player(); 8. player1.counter.value; // 1 9. 10. var player2 = new Player(); 11. player2.counter.value; // 2 12. player1.counter.value; // 2
  • 95.
    It is recommendedto define methods to all instances through object prototype. 95
  • 96.
    Instance Properties AndPrototype Properties 96 1. function Robot () { 2. this.walk = function () {} 3. } 4. Robot.prototype.talk = function () {}; 5. 6. var wat = new Robot(), eve = new Robot(); 7. 8. wat.walk === eve.walk; // false 9. wat.talk === eve.talk; // true 10. wat.talk === Robot.prototype.talk; // true 11. wat.hasOwnProperty('walk'); // true 12. wat.hasOwnProperty('talk'); // false
  • 97.
    Classical Inheritance WithObject.create() 97 1. function Bird () {} 2. Bird.prototype.fly = function () {}; 3. 4. function Pigeon () { Bird.call(this); } 5. Pigeon.prototype = Object.create(Bird.prototype); 6. Pigeon.prototype.constructor = Pigeon; 7. var pigeon = new Pigeon(); 8. 9. Pigeon.prototype.__proto__ === Bird.prototype; // true 10. pigeon.fly === Pigeon.prototype.fly; // true 11. pigeon.fly === Bird.prototype.fly; // true
  • 98.
    Override Methods 98 1. functionBird () {} 2. Bird.prototype.fly = function () { return 'Default'; }; 3. 4. function Eagle () { Bird.call(this); } 5. Eagle.prototype = Object.create(Bird.prototype); 6. Eagle.prototype.constructor = Eagle; 7. Eagle.prototype.fly = function () { return 'Overrode'; }; 8. var eagle = new Eagle(); 9. 10. Eagle.prototype.__proto__ === Bird.prototype; // true 11. eagle.fly === Eagle.prototype.fly; // true 12. eagle.fly === Bird.prototype.fly; // false
  • 99.
  • 100.
    Class Declarations 100 1. classBird { 2. constructor (type) { 3. this.type = type; 4. } 5. fly () { 6. console.log('Fly!'); 7. } 8. } 9. 10. typeof Bird; // 'function'
  • 101.
    Sub Classing Withextends 101 1. class Penguin extends Bird { 2. constructor () { 3. super('Penguin'); 4. } 5. fly () { 6. super.fly(); 7. console.log('Penguin Fly!'); 8. } 9. } 10. 11. Penguin.prototype.fly === Bird.prototype.fly; // false
  • 102.
    Static Methods 102 1. classFood { 2. static calorie () {} 3. } 4. 5. function Drink () {} 6. Drink.calorie = function () {}
  • 103.
    The best thingabout JavaScript is its implementation of functions. It got almost everything right. But, as you should expect with JavaScript, it didn't get everything right. - Douglas Crockford 103
  • 104.
  • 105.
    Reference 105 ● JavaScript |CodeData ● Prototype-based programming - Wikipedia ● First-class function - Wikipedia ● JavaScript Guide - JavaScript | MDN ● JavaScript Tutorial | W3Schools Practical JavaScript Programming
  • 106.
    Reference Books ● JavaScript:The Good Parts ● Effective JavaScript 106 Practical JavaScript Programming
  • 107.