Your SlideShare is downloading. ×
0
http://www.flickr.com/photos/tomsly/93947243/ - thomas_sly




A (Re)-Introduction to JavaScript
Simon Willison            ...
Coming up...

• Numbers, Strings and things
• Variables and Operators
• Control Structures
• Objects and Arrays
• Function...
Book recommendation

    • JavaScript: The
      Definitive Guide
      – by David Flanagan
    • Comprehensive
      over...
More book recommendations

• For practical applications of this stuff:




4

                                              4
You will need...

• Firefox
    – Any web browser can run JavaScript, but
      Firefox has the best tools for developers
...
In the words of its creator

        JavaScript was a rushed little hack for
    Netscape 2 that was then frozen premature...
http://www.flickr.com/photos/kingcoyote/93491484/ - King Coyote




The History of JavaScript
       (in 30 seconds)




  ...
JavaScript was...



       Invented by Brendan Eich in 1995 for
    Netscape; originally called LiveScript, current
    n...
Not quite general purpose

• No direct concept of input or output
• Runs within a host environment
    – Web browser
    –...
http://www.flickr.com/photos/olivepress/11223013/ - Brian Sawyer




Syntax


                                             ...
Reserved words

                 break else new var
              case finally return void
               catch for switch...
Style recommendations

• Avoid semi-colon insertion like the plague


     ;;;                        friends
• Declare va...
http://www.flickr.com/photos/kvitsh/64919318/ - K'vitsh / Heather Hutchinson




Types

                                   ...
JavaScript types

• Numbers
• Strings
• Booleans
• Functions
• Objects




14

                   14
JavaScript types (improved)

•    Number
•    String
•    Boolean
•    Object
     – Function
     – Array
     – Date
   ...
http://www.flickr.com/photos/51035555243@N01/72778694/ - Thomas Hawk




Numbers

                                         ...
Numbers

• quot;double-precision 64-bit format IEEE 754
  valuesquot;
• No such thing as an integer
     0.1 + 0.2 = 0.300...
Math stuff

• Math.PI, Math.E, Math.LN10,
  Math.LN2, Math.LOG10E,
  Math.SQRT1_2, Math.SQRT2
• Math.abs(x), Math.acos(x),...
parseInt (and parseFloat)

• parseInt converts a string to a number
       > parseInt(quot;123quot;);
       123
       > ...
NaN and Infinity

     > parseInt(quot;helloquot;, 10)
     NaN
• NaN is toxic
     > NaN + 5
     NaN
     > isNaN(NaN)
 ...
http://www.flickr.com/photos/solarider/53494967/ - solarider




Strings

                                                 ...
Strings

• Sequences of characters
• Sequences of unicode characters (16 bit)
     quot;u0020quot;
• A character is a stri...
String methods

     > quot;helloquot;.charAt(0)
     h
     > quot;hello, worldquot;.replace(quot;helloquot;,
     quot;g...
More string methods

         s.charAt(pos) s.charCodeAt(pos)
                   s.concat(s1, ..)
                s.indexO...
Null and undefined

• null = deliberately no value
• undefined = no value assigned yet
     – Variables declared but not i...
Booleans

• Boolean type: true or false
• Everything else is quot;truthyquot; or quot;falsyquot;
• 0, quot;quot;, NaN, nul...
http://www.flickr.com/photos/antmoose/71277315/ - antmoose / Anthony M.




Variables and operators

                      ...
Variable declaration

• New variables in JavaScript are declared
  using the var keyword:
       var a;
       var name = ...
Operators

     Numeric operators: +, -, *, / and %
• Compound assignment operators:
       +=, -=, *=, /=, %=
• Increment...
Type coercion

     > quot;3quot; + 4 + 5
     345
     > 3 + 4 + quot;5quot;
     75


• Adding an empty string to someth...
Comparison

• >, <, >=, <= work for numbers and strings
• Equality tests use == and != ... sort of
     > quot;dogquot; ==...
The typeof operator

     typeof v
                number      'number'
                string      'string'
             ...
http://www.flickr.com/photos/setre/8825214/ - setre




Control structures

                                               ...
if statements

     var name = quot;kittensquot;;
     if (name == quot;puppiesquot;) {
       name += quot;!quot;;
     }...
while and do-while

     while (true) {
         // an infinite loop!
     }


     do {
         var input = get_input();...
for loops

     for (var i = 0; i < 5; i++) {
       // Will execute 5 times
     }




36

                              ...
switch statement

• Multiple branches depending on a number or
  string
     switch(action) {
         case 'draw':
      ...
fall through

     switch(a) {
         case 1: // fallthrough
         case 2:
             eatit();
             break;
...
Switch expressions

• Expressions are allowed
• Comparisons take place using ===
     switch(1 + 3):
         case 2 + 2:
...
Short-circuit logic

• The && and || operators use short-circuit
  logic: they will execute their second operand
  dependa...
The tertiary operator

• One-line conditional statements
     var ok = (age > 18) ? quot;yesquot; : quot;noquot;;
• Easy t...
Exceptions

     try {
       // Statements in which
       // exceptions might be thrown
     } catch(error) {
       // ...
http://www.flickr.com/photos/spengler/51617271/ - Andreas D.




Objects

                                                 ...
Objects

• Simple name-value pairs, as seen in:
     – Dictionaries in Python
     – Hashes in Perl and Ruby
     – Hash t...
Basic object creation

     var obj = new Object();
• Or:
     var obj = {};
• These are semantically equivalent; the
  se...
Property access

     obj.name = quot;Simonquot;
     var name = obj.name;
• Or...
     obj[quot;namequot;] = quot;Simonqu...
Object literal syntax

 var obj = {
   name: quot;Carrotquot;,
   quot;forquot;: quot;Maxquot;,
   details: {
     color: ...
for (var attr in obj)

• You can iterate over the keys of an object:
     var obj = { 'name': 'Simon', 'age': 25};
     fo...
http://www.flickr.com/photos/adrian_s/28567268/ - waffler / Adrian Sampson




Arrays

                                     ...
Arrays

• A special type of object: Keys are whole
  numbers, not strings.
• Use [] syntax, just like objects
     > var a...
Array literals

• More convenient notation:
     > var a = [quot;dogquot;, quot;catquot;, quot;henquot;];
     > a.length
...
array.length

     > var a = [quot;dogquot;, quot;catquot;, quot;henquot;];
     > a[100] = quot;foxquot;;
     > a.length...
Array iteration

     for (var i = 0; i < a.length; i++) {
         // Do something with a[i]
     }



• Improve this by ...
Even better iteration

     for (var i = 0, item; item = a[i]; i++) {
         // Do something with item
     }

• This tr...
Array methods

          a.toString(), a.toLocaleString(),
     a.concat(item, ..), a.join(sep), a.pop(),
     a.push(item...
3.2




                                       2.4




                                       1.6




                    ...
Functions

• Don't get much simpler than this:
     function add(x, y) {
         var total = x + y;
         return total...
Arguments

• Parameters: quot;They're more like... guidelinesquot;
• Missing parameters are treated as undefined:
     > a...
arguments

• The arguments special variable provides
  access to arguments as an array-like object
     function add() {
 ...
avg()

• More useful: an averaging function:
     function avg() {
         var sum = 0;
         for (var i = 0, j = argu...
Averaging an array?

• Our fancy multi-argument function isn't much
  good if our data is already in an array. Do we
  hav...
Using avg() with an array

• That's not necessary:
     > avg.apply(null, [2, 3, 4, 5])
     3.5
• Functions are objects w...
Anonymous functions

• The following is semantically equivalent to
  our earlier avg() function:
     var avg = function()...
The block scope trick

• Block scope is a feature of C where every
  set of braces defines a new scope. It can be
  simula...
Recursive functions

     function countChars(elm) {
         if (elm.nodeType == 3) { // TEXT_NODE
             return el...
arguments.callee

• arguments.callee is the current function:
     var charsInBody = (function(elm) {
         if (elm.nod...
arguments.callee to save state

• This function remembers how many times it
  has been called:
     function counter() {
 ...
http://www.flickr.com/photos/45339031@N00/100472474/ - piccadillywilson / Matt




Constructors

                          ...
Functions and objects

     function makePerson(first, last) {
         return {
             first: first,
             l...
Functions and objects (II)

     > s = makePerson(quot;Simonquot;,
     quot;Willisonquot;);
     > personFullName(s)
    ...
Methods, first try

     function makePerson(first, last) {
       return {
         first: first,
         last: last,
  ...
Using methods

     > s = makePerson(quot;Simonquot;,
     quot;Willisonquot;)
     > s.fullName()
     Simon Willison
   ...
dot notation is required

     > s = makePerson(quot;Simonquot;,
     quot;Willisonquot;)
     > var fullName = s.fullName...
Constructors

     function Person(first, last) {
       this.first = first;
       this.last = last;
       this.fullName...
new

• 'new' creates a new empty object and calls
  the specified function with 'this' set to that
  object.
• These const...
Sharing methods

     function personFullName() {
         return this.first + ' ' +
             this.last;
     }
     f...
Person.prototype

     function Person(first, last) {
         this.first = first;
         this.last = last;
     }
     ...
instanceof

• The instanceof operator can be used to test
  the type of an object, based on its
  constructor (and prototy...
http://www.flickr.com/photos/bingolittle/5803243/ - Bingo Little




Inheritance

                                         ...
Adding to an existing set of objects

     > s = new Person(quot;Simonquot;,
     quot;Willisonquot;);
     > s.firstNameC...
Extending core objects

     > var s = quot;Simonquot;;
     > s.reversed()
     TypeError: s.reversed is not a function
 ...
Object.prototype

• All prototype chains terminate at
  Object.prototype
• Its methods include toString(), which we can
  ...
Perils of modifying Object.prototype

• Remember for (var attr in obj)?
• It will include stuff that's been newly added to...
So what about inheritance?

• Problem: JavaScript is a prototype-based
  language, but it pretends to be a class-based
  l...
Here's a special kind of person
     function Geek() {
       Person.apply(this, arguments);
       this.geekLevel = 5;
  ...
new Person()?

• We're using an instance of the Person object
  as our prototype
• We have to do this, because we need to ...
Solutions?

• Design classes with inheritance in mind -
  don't do anything important in the constructor
  (that might bre...
http://en.wikipedia.org/wiki/Image:Torres_Petronas_Mayo_2004.jpg Ángel Riesgo Martínez




Higher order functions

       ...
Functions are first-class objects

• In English...
     – A function is just another object
     – You can store it in a v...
VAT
VAT is England's national sales tax - 17.5%

     var prices = [10, 8, 9.50];
     var pricesVat = [];
     for (var i...
arrayMap
 function arrayMap(array, func) {
   var result = [];
   for (var i = 0; i < array.length; i++) {
     result[i] ...
salesTaxFactory
What if we want to calculate sales tax at 4%?

     function salesTaxFactory(percent) {
       function fu...
An operation factory
     function makeOp(op, y) {
       switch (op) {
         case '+':
           return function(x) {...
Closures

• The previous code was an example of
  closures in action
• A closure is a function that has captured the
  sco...
What does this do?
     function openLinksInNewWindows() {
         for (var i = 0; i < document.links.length; i++) {
    ...
http://www.flickr.com/photos/iboy_daniel/90450551/ - iboy_daniel / doug wilson




Singleton

                             ...
Namespace pollution

• JavaScript shares a single global
  namespace
• It’s easy to clobber other people’s functions
  and...
The singleton pattern
     var simon = (function() {
       var myVar = 5; // Private variable
       function init(x) {
 ...
Singleton benefits

• Singleton lets you wrap up a complex
  application with dozens of functions up in a
  single, privat...
http://www.flickr.com/photos/lunchtimemama/97685471/ - lunchtimemama / Scott




Memory leaks

                            ...
Internet Explorer sucks

• To understand memory leaks, you have to
  understand a bit about garbage collection
• Stuff get...
This leaks

      function leak() {
          var div = document.getElementById('d');
          div.obj = {

             ...
This also leaks

      function sneakyLeak() {
          var div = document.getElementById('d');
          div.onclick = f...
Difficulties

• These things can be very hard to detect -
  especially in large, complex applications
  where a cycle migh...
More solutions

• Most popular JavaScript libraries have
  systems for attaching and detaching events
• Many of these can ...
http://www.flickr.com/photos/javic/100567276/ - javic




Performance

                                            106
    ...
Performance tips

• De-reference complex lookups
      var s = document.getElementById('d').style;
      s.width = '100%';...
http://www.flickr.com/photos/klara/94704029/ - klara(!) / klara




Libraries

                                            ...
Suggested libraries



             ¯¯
          dojotoolkit.org
                                developer.yahoo.net/yui/
...
Tell Alex I told you this...
• Everything in JavaScript is an Object. Even
  functions
• Every object is always mutable
• ...
http://www.flickr.com/photos/nataliedowne/14517351/ - NatBat / Natalie Downe




Thank you!
                               ...
Upcoming SlideShare
Loading in...5
×

A Re-Introduction to JavaScript

15,577

Published on

Slides from a tutorial I gave at ETech 2006. Notes to accompany these slides can be found here: http://simonwillison.net/static/2006/js-reintroduction-notes.html

Published in: Technology, Education
5 Comments
44 Likes
Statistics
Notes
No Downloads
Views
Total Views
15,577
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
933
Comments
5
Likes
44
Embeds 0
No embeds

No notes for slide

Transcript of "A Re-Introduction to JavaScript"

  1. 1. http://www.flickr.com/photos/tomsly/93947243/ - thomas_sly A (Re)-Introduction to JavaScript Simon Willison ETech, March 6th, 2005 1 1
  2. 2. Coming up... • Numbers, Strings and things • Variables and Operators • Control Structures • Objects and Arrays • Functions • Object constructors and inheritance • Inner functions and closures • Memory Leaks... and more 2 2
  3. 3. Book recommendation • JavaScript: The Definitive Guide – by David Flanagan • Comprehensive overview of the language in the first 20 chapters • New edition out later this year 3 3
  4. 4. More book recommendations • For practical applications of this stuff: 4 4
  5. 5. You will need... • Firefox – Any web browser can run JavaScript, but Firefox has the best tools for developers • Jesse Ruderman's 'shell' tool – http://www.squarefree.com/shell/ • A text editor may come in handy too 5 5
  6. 6. In the words of its creator JavaScript was a rushed little hack for Netscape 2 that was then frozen prematurely during the browser wars, and evolved significantly only once by ECMA. So its early flaws were never fixed, and worse, no virtuous cycle of fine-grained community feedback in the form of standard library code construction, and revision of the foundational parts of the language to better support the standard library and its common use-cases, ever occurred. 6 http://weblogs.mozillazine.org/roadmap/archives/2006/02/js_and_python_news.html 6
  7. 7. http://www.flickr.com/photos/kingcoyote/93491484/ - King Coyote The History of JavaScript (in 30 seconds) 7 7
  8. 8. JavaScript was... Invented by Brendan Eich in 1995 for Netscape; originally called LiveScript, current name being an ill-fated marketing decision to tie in with Sun's newly released Java; adapted by Microsoft as JScript for IE 3 in 1996; standardised as ECMAScript in 1997; sort-of included in Flash as ActionScript; updated to ECMAScript 3rd edition in 1998 8 8
  9. 9. Not quite general purpose • No direct concept of input or output • Runs within a host environment – Web browser – Adobe Acrobat – Photoshop – Windows Scripting Host – Yahoo! Widget Engine – and more... 9 9
  10. 10. http://www.flickr.com/photos/olivepress/11223013/ - Brian Sawyer Syntax 10
  11. 11. Reserved words break else new var case finally return void catch for switch while continue function this with default if throw delete in try do instanceof typeof abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private transient debugger implements protected volatile double import public 11 11
  12. 12. Style recommendations • Avoid semi-colon insertion like the plague ;;; friends • Declare variables religiously with 'var' • Global variables are evil. Avoid them if you can. • Indent consistently 12 12
  13. 13. http://www.flickr.com/photos/kvitsh/64919318/ - K'vitsh / Heather Hutchinson Types 13 13
  14. 14. JavaScript types • Numbers • Strings • Booleans • Functions • Objects 14 14
  15. 15. JavaScript types (improved) • Number • String • Boolean • Object – Function – Array – Date – RegExp • Null • Undefined 15 15
  16. 16. http://www.flickr.com/photos/51035555243@N01/72778694/ - Thomas Hawk Numbers 16 16
  17. 17. Numbers • quot;double-precision 64-bit format IEEE 754 valuesquot; • No such thing as an integer 0.1 + 0.2 = 0.30000000000000004 3 + 5.3 28 % 6 etc... • Math namespace for advanced operations 17 17
  18. 18. Math stuff • Math.PI, Math.E, Math.LN10, Math.LN2, Math.LOG10E, Math.SQRT1_2, Math.SQRT2 • Math.abs(x), Math.acos(x), Math.asin(x), Math.atan(x), Math.atan2(y, x), Math.ceil(x), Math.cos(x), Math.exp(x), Math.floor(x), Math.log(x), Math.max(x, ..), Math.min(x, ..), Math.pow(x, y), Math.random(), Math.round(x), Math.sin(x), Math.sqrt(x), Math.tan(x) 18 18
  19. 19. parseInt (and parseFloat) • parseInt converts a string to a number > parseInt(quot;123quot;); 123 > parseInt(quot;010quot;); Always specify the base 8 • !? > parseInt(quot;010quot;, 10); 10 > parseInt(quot;11quot;, 2) 3 19 19
  20. 20. NaN and Infinity > parseInt(quot;helloquot;, 10) NaN • NaN is toxic > NaN + 5 NaN > isNaN(NaN) true • Special values for Infinity and -Infinity: >1/0 > -1 / 0 Infinity -Infinity 20 20
  21. 21. http://www.flickr.com/photos/solarider/53494967/ - solarider Strings 21 21
  22. 22. Strings • Sequences of characters • Sequences of unicode characters (16 bit) quot;u0020quot; • A character is a string of length 1 > quot;helloquot;.length 5 • Strings are objects! 22 22
  23. 23. String methods > quot;helloquot;.charAt(0) h > quot;hello, worldquot;.replace(quot;helloquot;, quot;goodbyequot;) goodbye, world > quot;helloquot;.toUpperCase() HELLO 23 23
  24. 24. More string methods s.charAt(pos) s.charCodeAt(pos) s.concat(s1, ..) s.indexOf(s1, start) s.lastIndexOf(s1, startPos) s.localeCompare(s1) s.match(re) s.replace(search, replace) s.search(re) s.slice(start, end) s.split(separator, limit) s.substring(start, end) s.toLowerCase() s.toLocaleLowerCase() s.toUpperCase() s.toLocaleUpperCase() 24 24
  25. 25. Null and undefined • null = deliberately no value • undefined = no value assigned yet – Variables declared but not initialised – Object/array members that don't exist – (More on this later) 25 25
  26. 26. Booleans • Boolean type: true or false • Everything else is quot;truthyquot; or quot;falsyquot; • 0, quot;quot;, NaN, null, undefined are falsy • Everything else is truthy • Boolean operations: &&, || and ! • Convert any value to it's boolean equivalent by applying not twice: > !!234 > !!quot;quot; true false 26 26
  27. 27. http://www.flickr.com/photos/antmoose/71277315/ - antmoose / Anthony M. Variables and operators 27 27
  28. 28. Variable declaration • New variables in JavaScript are declared using the var keyword: var a; var name = quot;simonquot;; • If you declare a variable without assigning it to anything, its value is undefined. If you forget the var, you get a global variable. Never, ever do this - not even if you mean it. 28 28
  29. 29. Operators Numeric operators: +, -, *, / and % • Compound assignment operators: +=, -=, *=, /=, %= • Increment and decrement: a++, ++a, b--, --b • String concatenation: > quot;helloquot; + quot; worldquot; hello world 29 29
  30. 30. Type coercion > quot;3quot; + 4 + 5 345 > 3 + 4 + quot;5quot; 75 • Adding an empty string to something else converts it to a string. 30 30
  31. 31. Comparison • >, <, >=, <= work for numbers and strings • Equality tests use == and != ... sort of > quot;dogquot; == quot;dogquot; true > 1 == true true • === and !== avoid type coercion > 1 === true false > true === true true 31 31
  32. 32. The typeof operator typeof v number 'number' string 'string' boolean 'boolean' function 'function' object 'object' array 'object' null 'object' undefined 'undefined' 32 32
  33. 33. http://www.flickr.com/photos/setre/8825214/ - setre Control structures 33 33
  34. 34. if statements var name = quot;kittensquot;; if (name == quot;puppiesquot;) { name += quot;!quot;; } else if (name == quot;kittensquot;) { name += quot;!!quot;; } else { name = quot;!quot; + name; } name == quot;kittens!!quot; 34 34
  35. 35. while and do-while while (true) { // an infinite loop! } do { var input = get_input(); } while (inputIsNotValid(input)) 35 35
  36. 36. for loops for (var i = 0; i < 5; i++) { // Will execute 5 times } 36 36
  37. 37. switch statement • Multiple branches depending on a number or string switch(action) { case 'draw': drawit(); break; case 'eat': eatit(); break; default: donothing(); } 37 37
  38. 38. fall through switch(a) { case 1: // fallthrough case 2: eatit(); break; default: donothing(); } • Deliberate labelling of fall through is good practise 38 38
  39. 39. Switch expressions • Expressions are allowed • Comparisons take place using === switch(1 + 3): case 2 + 2: yay(); break; default: neverhappens(); } 39 39
  40. 40. Short-circuit logic • The && and || operators use short-circuit logic: they will execute their second operand dependant on the first. • This is useful for checking for null objects before accessing their attributes: var name = o && o.getName(); • Or for setting default values: var name = otherName || quot;defaultquot;; 40 40
  41. 41. The tertiary operator • One-line conditional statements var ok = (age > 18) ? quot;yesquot; : quot;noquot;; • Easy to abuse; use with caution 41 41
  42. 42. Exceptions try { // Statements in which // exceptions might be thrown } catch(error) { // Statements that execute // in the event of an exception } finally { // Statements that execute // afterward either way } throw new Error(quot;An error!quot;); throw quot;Another error!quot;; 42 42
  43. 43. http://www.flickr.com/photos/spengler/51617271/ - Andreas D. Objects 43 43
  44. 44. Objects • Simple name-value pairs, as seen in: – Dictionaries in Python – Hashes in Perl and Ruby – Hash tables in C and C++ – HashMaps in Java – Associative arrays in PHP • Very common, versatile data structure • Name part is a string; value can be anything 44 44
  45. 45. Basic object creation var obj = new Object(); • Or: var obj = {}; • These are semantically equivalent; the second is called object literal syntax and is more convenient. 45 45
  46. 46. Property access obj.name = quot;Simonquot; var name = obj.name; • Or... obj[quot;namequot;] = quot;Simonquot;; var name = obj[quot;namequot;]; • Semantically equivalent; the second uses strings so can be decided at run-time (and can be used for reserved words) 46 46
  47. 47. Object literal syntax var obj = { name: quot;Carrotquot;, quot;forquot;: quot;Maxquot;, details: { color: quot;orangequot;, size: 12 } } > obj.details.color > obj[quot;detailsquot;][quot;sizequot;] orange 12 47 47
  48. 48. for (var attr in obj) • You can iterate over the keys of an object: var obj = { 'name': 'Simon', 'age': 25}; for (var attr in obj) { print (attr + ' = ' + obj[attr]); } • Don't attempt this with arrays (coming up next). There are safer ways of iterating over them. 48 48
  49. 49. http://www.flickr.com/photos/adrian_s/28567268/ - waffler / Adrian Sampson Arrays 49 49
  50. 50. Arrays • A special type of object: Keys are whole numbers, not strings. • Use [] syntax, just like objects > var a = new Array(); > a[0] = quot;dogquot;; > a[1] = quot;catquot;; > a[2] = quot;henquot;; > a.length 3 50 50
  51. 51. Array literals • More convenient notation: > var a = [quot;dogquot;, quot;catquot;, quot;henquot;]; > a.length 3 51 51
  52. 52. array.length > var a = [quot;dogquot;, quot;catquot;, quot;henquot;]; > a[100] = quot;foxquot;; > a.length 101 typeof a[90] == 'undefined' • array.length is always one more than the highest index • The safest way to append new items is: a[a.length] = item; 52 52
  53. 53. Array iteration for (var i = 0; i < a.length; i++) { // Do something with a[i] } • Improve this by caching a.length at start: for (var i = 0, j = a.length; i < j; i++) { // Do something with a[i] } 53 53
  54. 54. Even better iteration for (var i = 0, item; item = a[i]; i++) { // Do something with item } • This trick only works with arrays that are known not to contain falsy values. The following array will break with the above idiom: var a = [10, quot;dogquot;, false, quot;elephantquot;]; • (Yes, you can have mixed content in arrays) 54 54
  55. 55. Array methods a.toString(), a.toLocaleString(), a.concat(item, ..), a.join(sep), a.pop(), a.push(item, ..), a.reverse(), a.shift(), a.slice(start, end), a.sort(cmpfn), a.splice(start, delcount, [item]..), a.unshift([item]..) 55 55
  56. 56. 3.2 2.4 1.6 0.8 .8 -4 -3.2 -2.4 -1.6 -0.8 0 0.8 1.6 2.4 3.2 4 4.8 -0.8 Functions -1.6 -2.4 -3.2 56 56
  57. 57. Functions • Don't get much simpler than this: function add(x, y) { var total = x + y; return total; } • If nothing is explicitly returned, return value is undefined 57 57
  58. 58. Arguments • Parameters: quot;They're more like... guidelinesquot; • Missing parameters are treated as undefined: > add() Nan // addition on undefined • You can pass in more arguments than expected: > add(2, 3, 4) 5 // added the first two; 4 was ignored • How is this behaviour useful? 58 58
  59. 59. arguments • The arguments special variable provides access to arguments as an array-like object function add() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum; } > add(2, 3, 4, 5) 14 59 59
  60. 60. avg() • More useful: an averaging function: function avg() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum / arguments.length; } 60 60
  61. 61. Averaging an array? • Our fancy multi-argument function isn't much good if our data is already in an array. Do we have to rewrite it? function avgArray(arr) { var sum = 0; for (var i = 0, j = arr.length; i < j; i++) { sum += arguments[i]; } return sum / arr.length; } 61 61
  62. 62. Using avg() with an array • That's not necessary: > avg.apply(null, [2, 3, 4, 5]) 3.5 • Functions are objects with methods too! • The apply method takes an array of argments as the second argument... • We'll find out about the first argument a little later 62 62
  63. 63. Anonymous functions • The following is semantically equivalent to our earlier avg() function: var avg = function() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum / arguments.length; } 63 63
  64. 64. The block scope trick • Block scope is a feature of C where every set of braces defines a new scope. It can be simulated in JavaScript: var a = 1; var b = 2; (function() { var b = 3; a += b; })(); >a 4 >b 2 64 64
  65. 65. Recursive functions function countChars(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } var count = 0; for (var i = 0, child; child = elm.childNodes[i]; i++) { count += countChars(child); } return count; } 65 65
  66. 66. arguments.callee • arguments.callee is the current function: var charsInBody = (function(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } var count = 0; for (var i = 0, child; child = elm.childNodes[i]; i++) { count += arguments.callee(child); } return count; })(document.body); 66 66
  67. 67. arguments.callee to save state • This function remembers how many times it has been called: function counter() { if (!arguments.callee.count) { arguments.callee.count = 0; } return arguments.callee.count++; } > counter() 0 > counter() 1 67 67
  68. 68. http://www.flickr.com/photos/45339031@N00/100472474/ - piccadillywilson / Matt Constructors 68 68
  69. 69. Functions and objects function makePerson(first, last) { return { first: first, last: last } } function personFullName(person) { return person.first + ' ' + person.last; } function personFullNameReversed(person) { return person.last + ', ' + person.first } 69 69
  70. 70. Functions and objects (II) > s = makePerson(quot;Simonquot;, quot;Willisonquot;); > personFullName(s) Simon Willison > personFullNameReversed(s) Willison, Simon • Surely we can attach functions to the objects themselves? 70 70
  71. 71. Methods, first try function makePerson(first, last) { return { first: first, last: last, fullName: function() { return this.first + ' ' + this.last; }, fullNameReversed: function() { return this.last + ', ' + this.first; } } } 71 71
  72. 72. Using methods > s = makePerson(quot;Simonquot;, quot;Willisonquot;) > s.fullName() Simon Willison > s.fullNameReversed() Willison, Simon 72 72
  73. 73. dot notation is required > s = makePerson(quot;Simonquot;, quot;Willisonquot;) > var fullName = s.fullName; > fullName() undefined undefined • If you call a function without using dot notation, 'this' is set to the global object. In the browser, this is the same as 'window'. 73 73
  74. 74. Constructors function Person(first, last) { this.first = first; this.last = last; this.fullName = function() { return this.first + ' ' + this.last; } this.fullNameReversed = function() { return this.last + ', ' + this.first; } } var s = new Person(quot;Simonquot;, quot;Willisonquot;); 74 74
  75. 75. new • 'new' creates a new empty object and calls the specified function with 'this' set to that object. • These constructor functions should be Capitalised, as a reminder that they are designed to be called using 'new' • This is key to understanding JavaScript's object model 75 75
  76. 76. Sharing methods function personFullName() { return this.first + ' ' + this.last; } function personFullNameReversed() { return this.last + ', ' + this.first; } function Person(first, last) { this.first = first; this.last = last; this.fullName = personFullName; this.fullNameReversed = personFullNameReversed; } 76 76
  77. 77. Person.prototype function Person(first, last) { this.first = first; this.last = last; } Person.prototype.fullName = function() { return this.first + ' ' + this.last; } Person.prototype.fullNameReversed = function() { return this.last + ', ' + this.first; } 77 77
  78. 78. instanceof • The instanceof operator can be used to test the type of an object, based on its constructor (and prototype hierarchy, explained in the next section). var a = [1, 2, 3]; a instanceof Array true a instanceof Object true a instanceof String false 78 78
  79. 79. http://www.flickr.com/photos/bingolittle/5803243/ - Bingo Little Inheritance 79 79
  80. 80. Adding to an existing set of objects > s = new Person(quot;Simonquot;, quot;Willisonquot;); > s.firstNameCaps(); TypeError on line 1: s.firstNameCaps is not a function > Person.prototype.firstNameCaps = function() { return this.first.toUpperCase() } > s.firstNameCaps() SIMON 80 80
  81. 81. Extending core objects > var s = quot;Simonquot;; > s.reversed() TypeError: s.reversed is not a function > String.prototype.reversed = function() { var r = ''; for (var i = this.length - 1; i >= 0; i--){ r += this[i]; } return r; } > s.reversed() nomiS > quot;This can now be reversedquot;.reversed() desrever eb won nac sihT 81 81
  82. 82. Object.prototype • All prototype chains terminate at Object.prototype • Its methods include toString(), which we can over-ride: > var s = new Person(quot;Simonquot;, quot;Willisonquot;); >s [object Object] > Person.prototype.toString = function() { return '<Person: ' + this.fullName() + '>'; } >s <Person: Simon Willison> 82 82
  83. 83. Perils of modifying Object.prototype • Remember for (var attr in obj)? • It will include stuff that's been newly added to Object.prototype • This stupid behaviour is sadly baked in to the language • Some libraries (Prototype is a prime offender) do it anyway 83 83
  84. 84. So what about inheritance? • Problem: JavaScript is a prototype-based language, but it pretends to be a class-based language • As a result, it doesn't do either very well • Inheritance doesn't quite behave how you would expect 84 84
  85. 85. Here's a special kind of person function Geek() { Person.apply(this, arguments); this.geekLevel = 5; } Geek.prototype = new Person(); Geek.prototype.setLevel = function(lvl) { this.geekLevel = lvl; } Geek.prototype.getLevel = function() { return this.geekLevel; } > s = new Geek(quot;Simonquot;, quot;Willisonquot;) > s.fullName() Simon Willison > s.getLevel() 5 85 85
  86. 86. new Person()? • We're using an instance of the Person object as our prototype • We have to do this, because we need to be able to modify our prototype to add new methods that are only available to Geek instances • This is counter-intuitive and, well, a bit dumb 86 86
  87. 87. Solutions? • Design classes with inheritance in mind - don't do anything important in the constructor (that might break if you create an empty instance for use as a prototype) • Use one of the many workarounds – Prototype's Class.create() – The stuff you get by searching for quot;javascript inheritancequot; on the Web 87 87
  88. 88. http://en.wikipedia.org/wiki/Image:Torres_Petronas_Mayo_2004.jpg Ángel Riesgo Martínez Higher order functions 88 88
  89. 89. Functions are first-class objects • In English... – A function is just another object – You can store it in a variable – You can pass it to another function – You can return it from a function 89 89
  90. 90. VAT VAT is England's national sales tax - 17.5% var prices = [10, 8, 9.50]; var pricesVat = []; for (var i = 0; i < prices.length; i++) { pricesVat[i] = prices[i] * 1.175; } 90 90
  91. 91. arrayMap function arrayMap(array, func) { var result = []; for (var i = 0; i < array.length; i++) { result[i] = func(array[i]); } return result; } function calcVat(price) { return price * 1.175; } var prices = [10, 8, 9.50]; pricesVat = arrayMap(prices, calcVat); 91 91
  92. 92. salesTaxFactory What if we want to calculate sales tax at 4%? function salesTaxFactory(percent) { function func(price) { return price + (percent / 100) * price; } return func; } calcVat = salesTaxFactory(17.5); calc4 = salesTaxFactory(4); pricesVat = arrayMap(prices, calcVat); prices4 = arrayMay(prices, calc4); 92 92
  93. 93. An operation factory function makeOp(op, y) { switch (op) { case '+': return function(x) { return x + y }; case '-': return function(x) { return x - y }; case '/': return function(x) { return x / y }; case '*': return function(x) { return x * y }; default: return function(x) { return x }; } } var third = makeOp('/', 3); var dbl = makeOp('*', 2); print(third(24)); print(dbl(5)); 93 93
  94. 94. Closures • The previous code was an example of closures in action • A closure is a function that has captured the scope in which it was defined • Actually, functions in JavaScript have a scope chain (similar to the prototype chain) 94 94
  95. 95. What does this do? function openLinksInNewWindows() { for (var i = 0; i < document.links.length; i++) { document.links[i].onclick = function() { window.open(document.links[i].href); return false; } } } • The onclick function is a closure which refers back to the original scope; it does NOT retain a copy of the i variable at the time the function was created. By the time the onclick function is executed, i will be the last value assigned by the loop. 95 95
  96. 96. http://www.flickr.com/photos/iboy_daniel/90450551/ - iboy_daniel / doug wilson Singleton 96 96
  97. 97. Namespace pollution • JavaScript shares a single global namespace • It’s easy to clobber other people’s functions and variables • It’s easy for other people to clobber yours • The less code affecting the global namespace the better 97 97
  98. 98. The singleton pattern var simon = (function() { var myVar = 5; // Private variable function init(x) { // ... can access myVar and doPrivate } function doPrivate(x) { // ... invisible to the outside world } function doSomething(x, y) { // ... can access myVar and doPrivate } return { 'init': init, 'doSomething': doSomething } })(); simon.init(x); 98 98
  99. 99. Singleton benefits • Singleton lets you wrap up a complex application with dozens of functions up in a single, private namespace - a closure • This lets you expose only the functions that make up your application's external interface 99 99
  100. 100. http://www.flickr.com/photos/lunchtimemama/97685471/ - lunchtimemama / Scott Memory leaks 100 100
  101. 101. Internet Explorer sucks • To understand memory leaks, you have to understand a bit about garbage collection • Stuff gets freed up automatically when it is no longer in use (both JavaScript objects and host objects, such as DOM nodes) • IE uses different garbage collectors for JS and for the DOM, and can't handle circular references between them 101 101
  102. 102. This leaks function leak() { var div = document.getElementById('d'); div.obj = { 'leak': div } } • Call it enough times and IE will crash 102 102
  103. 103. This also leaks function sneakyLeak() { var div = document.getElementById('d'); div.onclick = function() { alert(quot;hi!quot;); } } • Why? Spot the closure! 103 103
  104. 104. Difficulties • These things can be very hard to detect - especially in large, complex applications where a cycle might occur over many nodes and JavaScript objects • One solution: function noLeak() { var div = document.getElementById('d'); div.onclick = function() { alert(quot;hi!quot;); } div = null; } 104 104
  105. 105. More solutions • Most popular JavaScript libraries have systems for attaching and detaching events • Many of these can automatically free event references when the page is unloaded • Use these, but always be aware of the problem 105 105
  106. 106. http://www.flickr.com/photos/javic/100567276/ - javic Performance 106 106
  107. 107. Performance tips • De-reference complex lookups var s = document.getElementById('d').style; s.width = '100%'; s.color = 'red'; // ... s.display = 'block'; • ... especially inside loops var lookup = foo.bar.bav; for (var i = 0; i < 1000; i++) { lookup.counter += someCalc(); } 107 107
  108. 108. http://www.flickr.com/photos/klara/94704029/ - klara(!) / klara Libraries 108 108
  109. 109. Suggested libraries ¯¯ dojotoolkit.org developer.yahoo.net/yui/ prototype.conio.net mochikit.com script.aculo.us 109 109
  110. 110. Tell Alex I told you this... • Everything in JavaScript is an Object. Even functions • Every object is always mutable • The dot operator is equivalent to de-referencing by hash (e.g., foo.bar === foo[quot;barquot;]) • The new keyword creates an object that class constructors run inside of, thereby imprinting them • Functions are always closures (combine w/ previous rule to create OOP) • The this keyword is relative to the execution context, not the declaration context • The prototype property is mutable 110 110
  111. 111. http://www.flickr.com/photos/nataliedowne/14517351/ - NatBat / Natalie Downe Thank you! 111 111
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×