Download presentation
Presentation is loading. Please wait.
Published byEunice Bruce Modified over 9 years ago
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
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
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.