Presentation is loading. Please wait.

Presentation is loading. Please wait.

Advanced JavaScript: closures, prototypes, inheritance Stoyan Stefanov Ajax Experience, Boston 2008.

Similar presentations


Presentation on theme: "Advanced JavaScript: closures, prototypes, inheritance Stoyan Stefanov Ajax Experience, Boston 2008."— Presentation transcript:

1 Advanced JavaScript: closures, prototypes, inheritance Stoyan Stefanov Ajax Experience, Boston 2008

2 About the presenter Yahoo! performance team member YSlow 2.0 architect, dev Book author, open-source contributor Blog: http://phpied.comhttp://phpied.com

3 Before we start… Firebug console

4 Firebug console is a learning tool

5 Firebug console… Inspect the contents of objects by clicking on them Tab auto-complete, a.k.a cheatsheet Arrows ↑ and ↓ Fiddle with any page

6 Any page…

7 Fiddle…

8 Objects

9 JavaScript data types primitive and objects number string boolean undefined null

10 What’s an object? a hash of key => value pairs if a key (property) happens to be a function, we can call it a method

11 What’s an object? var obj = { shiny: true, isShiny: function() { return this.shiny; } }; obj.isShiny(); // true

12 Object literal notation { Wrapped in curly braces },-delimited properties key:value pairs var obj = {a: 1, "b c d": 2};

13 Arrays

14 arrays are also objects auto-incremented properties

15 Arrays >>> var a = [1,3,2]; >>> a[0] 1 >>> typeof a "object"

16 Arrays array objects also get some cool properties... >>> a.length 3...and methods >>> a.sort() >>> a.join(' < ') "1 < 2 < 3"

17 Array literal notation var array = [ "Square", "brackets", "wrap", "the", "comma-delimited", "elements" ];

18 JSON JavaScript Object Notation Uses object and array literals Quotes required for properties {"num": 1, "str": "abc", "arr": [1,2,3]}

19 Functions

20 functions are objects they have properties they have methods can de copied, deleted, augmented... special feature: invokable

21 Functions function boo(what) { return what; } or var boo = function(what) { return what; };

22 Functions function boo(what) { return what; } or var boo = function bootoo(what) { return what; };

23 Functions are objects >>> boo.length 1 >>> boo.name "bootoo"

24 Functions are objects >>> var foo = boo; >>> foo("doodles") "doodles" >>> foo.call(null, "moo!"); "moo!"

25 Return value all functions return a value if they don't explicitly, they return undefined implicitly functions can return other functions

26 Constructors

27 when invoked with new, functions return an object known as this you have a chance of modifying this before it's returned you can also return some other object

28 Constructor functions var Person = function(name) { this.name = name; this.speaks = 'fr'; this.say = function() { return "Je m'appelle " + this.name; };

29 An object created with constructor >>> var julien = new Person("Julien"); >>> julien.say(); "Je m'appelle Julien"

30 Constructor’s return value var Person = function(){ this.first = "Bruce"; return {last: "Wayne"}; }; >>> typeof new Person().first "undefined" >>> new Person().last "Wayne"

31 Constructor’s return value var Person = function(){ this.first = "Bruce"; return "Batman"; }; >>> new Person().first "Bruce"

32 Naming convention MyConstructor myFunction

33 constructor property >>> function Person(){}; >>> var jo = new Person(); >>> jo.constructor === Person true

34 constructor property >>> var o = {}; >>> o.constructor === Object true >>> [1,2].constructor === Array true

35 Built-in constructor functions Object Array Function RegExp Number String Boolean Date Error, SyntaxError, ReferenceError…

36 Use thisNot that var o = {};var o = new Object(); var a = [];var a = new Array(); var re = /[a-z]/gmi; var re = new RegExp( '[a-z]', 'gmi'); var fn = function(a, b){ return a + b; } var fn = new Function( 'a, b','return a+b');

37 Wrapper objects vs. primitive >>> typeof new Number(1) "object" >>> typeof 1 "number"

38 Primitives can act as objects >>> "test".length 4 >>> (123.456).toFixed(2) "123.46"

39 Prototype

40 prototype a property of the function objects >>> var boo = function(){}; >>> typeof boo.prototype "object"

41 Prototypes can be augmented >>> boo.prototype.a = 1; >>> boo.prototype.sayAh = function(){};

42 Prototypes can be overwritten >>> boo.prototype = {a: 1, b: 2};

43 How is the prototype used? when a function is invoked as a constructor var Person = function(name) { this.name = name; }; Person.prototype.say = function() { return this.name; }

44 >>> var dude = new Person('dude'); >>> dude.name; "dude" >>> dude.say(); "dude" How is the prototype used?

45 say() is a property of the prototype object but it behaves as if it's a property of the dude object can we tell the difference? How is the prototype used?

46 Own properties vs. prototype’s >>> dude.hasOwnProperty('name'); true >>> dude.hasOwnProperty('say'); false

47 isPrototypeOf() >>> Person.prototype.isPrototypeOf(dude); true >>> Object.prototype.isPrototypeOf(dude); true

48 __proto__ I, the dude, have a secret link to the prototype of the constructor that created me __proto__ is not directly exposed in all browsers

49 >>> dude.__proto__.hasOwnProperty('say') true >>> dude.prototype ??? // Trick question >>> dude.__proto__.__proto__.hasOwnProperty('toString') true __proto__

50 The prototype chain

51 It’s alive! >>> typeof dude.numlegs "undefined" >>> Person.prototype.numlegs = 2; >>> dude.numlegs 2

52 Inheritance

53 Inheritance via the prototype >>> var Dad = function(){this.family = "Stefanov";}; >>> var Kid = function(){}; >>> Kid.prototype = new Dad(); >>> var billy = new Kid(); >>> billy.family "Stefanov"

54 Inherit one more time >>> var GrandKid = function(){}; >>> GrandKid.prototype = billy; >>> var jill = new GrandKid(); >>> jill.family "Stefanov"

55 Inheritance… >>> jill.hasOwnProperty('family') false >>> jill.__proto__.hasOwnProperty('family') false >>> jill.__proto__.__proto__.hasOwnProperty('family') true

56 Inheritance… >>> billy.family = 'Idol'; >>> jill.family; 'Idol' >>> jill.__proto__.hasOwnProperty('family'); true >>> delete billy.family; >>> jill.family; 'Stefanov'

57 Side effect… >>> billy.constructor === Kid false >>> billy.constructor === Dad true

58 Side effect… easy to solve reset after inheritance >>> Kid.prototype.constructor = Kid; >>> GrandKid.prototype.constructor = GrandKid;

59 isPrototypeOf >>> billy.isPrototypeOf(jill) true >>> Kid.prototype.isPrototypeOf(jill) true

60 instanceof >>> jill instanceof GrandKid true >>> jill instanceof Kid true >>> jill instanceof Dad true

61 Classes? There are no classes in JavaScript Objects inherit from objects classical inheritance is when we think of constructors as if they were classes

62 Classical inheritance function Parent(){this.name = 'parent';} Parent.prototype.getName = function(){ return this.name; }; function Child(){} inherit(Child, Parent);

63 Option 1 function inherit(C, P) { C.prototype = new P(); }

64 Option 2 function inherit(C, P) { C.prototype = P.prototype; }

65 Option 3 function inherit(C, P) { var F = function(){}; F.prototype = P.prototype; C.prototype = new F(); }

66 Option 3 + super function inherit(C, P) { var F = function(){}; F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; }

67 Option 3 + super + constructor reset function inherit(C, P) { var F = function(){}; F.prototype = P.prototype; C.prototype = new F(); C.uber = P.prototype; // super C.prototype.constructor = C; // reset }

68 Inheritance by copying properties After all, inheritance is all about code reuse function extend(parent) { var i, child = {}; for (i in parent) { child[i] = parent[i]; } return child; }

69 Inheritance by copying… >>> var parent = {a: 1}; >>> var child = extend(parent); >>> child.a 1

70 Inheritance by copying… This was a shallow copy you can make a deep copy using recursion mixins / multiple inheritance

71 Prototypal inheritance as suggested by Douglas Crockford no class-like constructors involved objects inherit from objects via the prototype

72 Prototypal inheritance function object(o) { function F(){} F.prototype = o; return new F(); }

73 Prototypal inheritance >>> var parent = {a: 1}; >>> var child = object(parent); >>> child.a; 1 >>> child.hasOwnProperty(a); false

74 Scope

75 No block scope >>> if (true) {var inside_block = 1;} >>> inside_block 1

76 Function scope function boo() { var inboo = true; }

77 Global namespace every variable is global unless it's in a function and is declared with var global namespace should be kept clean to avoid naming collisions function scope can help

78 Self-executable functions for one-off tasks (function(){ var a = 1; var b = 2; alert(a + b); })()

79 Closures

80 Photo credit: NASANASA

81

82 Closure example #1 function outer(){ var local = 1; return function(){ return local; }; }

83 example #1… >>> var inner = outer() >>> inner() 1

84 Closure example #2 var inner; function outer(){ var local = 1; inner = function(){ return local; }; }

85 example #2… >>> typeof inner "undefined" >>> outer() >>> inner() 1

86 Closure example #3 function makePlus(arg) { var n = function(){ return arg; }; arg++; return n; }

87 example #3… >>> var getValue = makePlus(1234); >>> getValue() 1235

88 Closure #4 – in a loop function make() { var i, a = []; for(i = 0; i < 3; i++) { a[i] = function(){ return i; } return a; }

89 Closure #4 test - oops >>> var funcs = make(); >>> funcs[0](); 3 >>> funcs[1](); 3 >>> funcs[2](); 3

90 Closure #4 – corrected function make() { var i, a = []; for(i = 0; i < 3; i++) { a[i] = (function(local){ return function(){return local;} })(i) } return a; }

91 Getter/Setter var getValue, setValue; (function() { var secret = 0; getValue = function(){ return secret; }; setValue = function(v){ secret = v; }; })() // usage >>> getValue() 0 >>> setValue(123) >>> getValue() 123

92 Iterator function setup(x) { var i = 0; return function(){ return x[i++]; }; }

93 Iterator usage >>> var next = setup(['a', 'b', 'c']); >>> next() 'a' >>> next() 'b'

94 Loop through DOM elements - wrong // all elements will alert 5 for (var i = 1; i < 5; i++ ){ document.getElementById('btn'+i).onclick = function(){ alert(i); }; }

95 Loop through DOM elements - correct // first element alerts 1, second 2,... for (var i = 1; i < 5; i++ ){ document.getElementById('btn'+i).onclick = (function(i){ return function(){alert(i);}; })(i) }

96 Wrapping up… How to tell what’s going on? typeof, instanceof, isPrototypeOf()…

97 >>> typeof variable typeof is an operator, not a function Not typeof(variable) even if it works Returns a string, one of: "string", "number", "boolean", "undefined", "object", "function"

98 typeof if (typeof whatever === "undefined") { // whatever is not defined } if (whatever == undefined) { // hmm, not so sure }

99 >>> obj instanceof MyConstructor Not instanceof() Returns true | false true for all constructors up the chain

100 >>> obj.constructor Points to the constructor function used to create this obj

101 >>> obj.isPrototypeOf(child_obj) Respects the prototype chain

102 >>> obj.hasOwnProperty("prop") Own properties vs. properties of the prototype

103 obj.propertyIsEnumerable("prop") Will it show up in a for-in loop Caution: enumerable properties of the prototype will return false but still show up in the for-in loop

104 Wrapping up… What did we learn today?

105 Objects JavaScript has a few primitive types, everything else is an object Objects are hashes Arrays are objects

106 Functions Functions are objects, only invokable call() and apply() methods prototype property

107 Prototype Functions have a prototype property which is an object Useful with Constructor functions

108 Constructor A function meant to be called with new Returns an object

109 Class No such thing in JavaScript

110 Inheritance Prototypal Classical … and approximately 101 other ways and variations

111 Scope Lexical function scope

112 Closure When a variable leaves its function scope

113 Thank you! Stoyan Stefanov http://www.phpied.com


Download ppt "Advanced JavaScript: closures, prototypes, inheritance Stoyan Stefanov Ajax Experience, Boston 2008."

Similar presentations


Ads by Google