JavaScript för Javautvecklare

2,635 views

Published on

My Jfokus 2012 tutorial "JavaScript för Javautvecklare". Natural language parts are in Swedish.

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,635
On SlideShare
0
From Embeds
0
Number of Embeds
29
Actions
Shares
0
Downloads
25
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

JavaScript för Javautvecklare

  1. 1. JavaScript förJavautvecklareJohn Wilander, Handelsbanken @johnwilander Jfokus 2012
  2. 2. shouldilearnjavascript.com
  3. 3. Java TyperPrimitiva:byte, short, int, long, float, double,boolean, charResten är objekt, s.k. referenstyperJavaScript Primitiva: string, number, boolean, function, undefined Resten är object
  4. 4. Java TyperPrimitiva:byte, short, int, long, float, double,boolean, charResten är objekt, s.k. referenstyperJavaScript Primitiva: string, number, boolean, function, undefined Resten är object
  5. 5. Java TyperPrimitiva:byte, short, int, long, float, double,boolean, charinte Strängar är generella objektResten är objekt, s.k.typ utan en egen referenstyperJavaScript Primitiva: string, number, boolean, function, undefined Resten är object
  6. 6. Java TyperPrimitiva: finns bara en Det typ för tal,byte, short, int, long, float, double,boolean, char det oavsett om är heltal ellerResten är objekt, s.k. referenstyper decimaltalJavaScript Primitiva: string, number, boolean, function, undefined Resten är object
  7. 7. Java TyperPrimitiva:byte, short, int, long, float, double,boolean, char Funktioner är fullödiga objektResten är objekt, s.k. referenstyper med en egen typJavaScript Primitiva: string, number, boolean, function, undefined Resten är object
  8. 8. Java TyperPrimitiva:byte, short, int, long, float, double,boolean, charJavaScripts version avResten oinitialiserad är är objekt, s.k. referenstyperJavaScript undefined Primitiva: string, number, boolean, function, undefined Resten är object
  9. 9. JavaScript Låt oss testa typeof 10 typeof 10.3 typeof Math.LN2 typeof Infinity typeof NaN typeof ”tutorial” typeof ”” typeof (typeof 10)
  10. 10. JavaScript Låt oss testa typeof 10 typeof 10.3 typeof Math.LN2 typeof Infinity typeof NaN typeof Number(10) typeof ”tutorial” typeof ”” typeof (typeof 10) typeof String(”tutorial”)
  11. 11. JavaScript Låt oss testa typeof undefined typeof tutorial typeof {} typeof [] typeof [4, 6, 2] typeof new Date()
  12. 12. JavaScript Låt oss testa typeof undefined typeof tutorial typeof {} typeof [] typeof [4, 6, 2] typeof new Date() typeof new Boolean(true) typeof new Number(10) typeof new String(”tutorial”)
  13. 13. Statisk vs dynamisk typningJavaStatisk typning:String name; Variabler har typername = ”John”; Värden har typername = 34; Variabler kan inte byta typJavaScript Dynamisk typning: var name; Variabler har inga typer name = ”John”; Värden har typer name = 34; Variabler byter typ dynamiskt
  14. 14. Dynamisk typningJavaScript var name = ”John”; Variabler har Värden har typer inga typer
  15. 15. Stark vs svag typning
  16. 16. Stark vs svag typning Stark !== bra Svag !== dålig
  17. 17. Java Stark vs svag typningint intVar = 4; Ganska stark typningintVar + ””; Implicit typkonverteringintVar + 0.0; Implicit, breddande typkonv.intVar + (int)0.0; Explicit typkonverteringintVar + null; Inte tillåtetJavaScript var dynVar = 4; Mycket svag typning dynVar + ””; Implicit typkonvertering dynVar + null; Implicit typkonvertering dynVar + []; Implicit typkonvertering dynVar + [0]; Implicit typkonvertering
  18. 18. Typsäkert ≈inga typfel vid körning
  19. 19. Johns slutsats Java är ett statiskt, starkt typat språk med hyfsat god typsäkerhetJavaScript är ett dynamiskt, svagt typat språk med hyfsat god typsäkerhet
  20. 20. Objektorientering
  21. 21. Java: Klasser och objekt Objekt Klass Objekt ExekverandeKällkod Objekt kod Singleton Klass -instans
  22. 22. JavaScript: Funktioner, objekt och prototyper Objekt Prototyp Objekt ExekverandeKällkod Objekt kod Funktion Funktion
  23. 23. JavaScript: Funktioner, objekt och prototyper Objekt Prototyp Objekt ExekverandeKällkod Objekt kod Funktion Anonyma closures Funktion Moduler
  24. 24. Java: Utökning med arv Subklass extends Superklass
  25. 25. Java: Subtypning med arv Supertyp extends Subtyp
  26. 26. Javaklasser blirfunktionsmässigt större och typmässigt mindre (mer specifika) via arv
  27. 27. I JavaScript så är utökning och subtypning skilda saker
  28. 28. JavaScript: Utökning via prototypJavaScript JW = {}; log = console.log; JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Base.prototype.sum = function() { return this.x + this.y; } JW.instance = new JW.Base(1, 2); log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  29. 29. JavaScript: Utökning via prototypJavaScript JW = {}; log = console.log; JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Base.prototype.sum = function() { return this.x + this.y; } JW.instance = new JW.Base(1, 2); log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  30. 30. JavaScript: Utökning via prototypJavaScript JW = {}; log = console.log; JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Base.prototype.sum = function() { return this.x + this.y; } JW.instance = new JW.Base(1, 2); log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  31. 31. JavaScript: Utökning via prototypJavaScript JW = {}; log = console.log; JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Base.prototype.sum = function() { return this.x + this.y; } JW.instance = new JW.Base(1, 2); log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  32. 32. JavaScript: Utökning via prototypJavaScript Användning av new innebär att: JW = {}; log = console.log; 1) ett nytt objekt skapas med JW.Base = function(x,JW.Base och att prototypen för y) { this.x 2) funktionen JW.Base() = x; this.y = y; }; anropas med this pekandes på JW.Base.prototype.sum = function() { den nya instansen return this.x + this.y; } JW.instance = new JW.Base(1, 2); log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  33. 33. JavaScript: Utökning via prototypJavaScript JW = {}; log = console.log; JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Base.prototype.sum = function() { return this.x + this.y; } JW.instance = new JW.Base(1, 2); log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  34. 34. JavaScript: Utökning via prototypJavaScript JW = {}; log = console.log; JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Base.prototype.sum = function() { return this.x + this.y; } JW.instance = new JW.Base(1, 2); log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  35. 35. JavaScript: Utökning via prototypJavaScript JW = {}; log = console.log; JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.instance = new JW.Base(1, 2); JW.Base.prototype.sum = function() { return this.x + this.y; } log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  36. 36. JavaScript: Utökning via prototypJavaScript JW = {}; log = console.log; JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.instance vi inte har skapat någon ny subtyp. Notera att = new JW.Base(1, 2); JW.Base.prototype.sumbefintliga (proto-)typen. Vi har bara utökat den = function() { return this.x + this.y; } log(JW.instance instanceof JW.Base); log(JW.instance.sum());
  37. 37. JavaScript JavaScript: Subtypning JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Extension = function(x, y, z) { JW.Base.call(this, x, y); this.z = z; }; JW.Extension.prototype = Object.create(JW.Base.prototype); JW.Extension.prototype.constructor = JW.Extension; JW.instance = new JW.Extension(1, 2, 3); log(JW.instance instanceof JW.Base);
  38. 38. JavaScript JavaScript: Subtypning JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Extension = function(x, y, z) { JW.Base.call(this, x, y); this.z = z; ju bara programmera Java Nu försöker vi }; i JavaScript. Ni ser ju själva vilket elände det blir. JW.Extension.prototype = Nåja, låt oss gå igenom det i alla fall. Object.create(JW.Base.prototype); JW.Extension.prototype.constructor = JW.Extension; JW.instance = new JW.Extension(1, 2, 3); log(JW.instance instanceof JW.Base);
  39. 39. JavaScript JavaScript: Subtypning JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Extension = function(x, y, z) { JW.Base.call(this, x, y); this.z = z; }; JW.Extension.prototype = Object.create(JW.Base.prototype); JW.Extension.prototype.constructor = JW.Extension; JW.instance = new JW.Extension(1, 2, 3); log(JW.instance instanceof JW.Base);
  40. 40. JavaScript JavaScript: Subtypning JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Extension = function(x, y, z) { JW.Base.call(this, x, y); this.z = z; }; JW.Extension.prototype = Object.create(JW.Base.prototype); JW.Extension.prototype.constructor = JW.Extension; JW.instance = new JW.Extension(1, 2, 3); log(JW.instance instanceof JW.Base);
  41. 41. JavaScript JavaScript: Subtypning JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Extension = function(x, y, z) { JW.Base.call(this, x, y); this.z = z; }; JW.Extension.prototype = Object.create(JW.Base.prototype); JW.Extension.prototype.constructor = JW.Extension; JW.instance = new JW.Extension(1, 2, 3); log(JW.instance instanceof JW.Base);
  42. 42. JavaScript JavaScript: Subtypning JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Extension = function(x, y, z) { JW.Base.call(this, x, y); this.z = z; }; JW.Extension.prototype = Object.create(JW.Base.prototype); JW.Extension.prototype.constructor = JW.Extension; JW.instance = new JW.Extension(1, 2, 3); log(JW.instance instanceof JW.Base);
  43. 43. JavaScript JavaScript: Subtypning JW.Base = function(x, y) { this.x = x; this.y = y; }; JW.Extension = function(x, y, z) { JW.Base.call(this, x, y); this.z = z; }; JW.Extension.prototype = Object.create(JW.Base.prototype); JW.Extension.prototype.constructor = JW.Extension; JW.instance = new JW.Extension(1, 2, 3); log(JW.instance instanceof JW.Base);
  44. 44. Varför vill vi subtypa? Jo, för att vi tänker i statisk typning och is-a-relationer
  45. 45. Statisk typning och subtypningJava public void doPurchase(List<Item> items) Kan ta emot en lista av Items eller subtyper till Item
  46. 46. Dynamisk typningJavaScript public void doPurchase(List<Item> items)
  47. 47. Dynamisk typningJavaScript public void doPurchase(List<Item> items)
  48. 48. Dynamisk typningJavaScript public void doPurchase(List<Item> items)
  49. 49. Dynamisk typningJavaScript public void doPurchase(List<Item> items)
  50. 50. Dynamisk typningJavaScript function doPurchase(items) Kan ta emot vad som helst ... eller ingenting
  51. 51. Dynamisk typningJavaScript function doPurchase(items) Kan returnera vad som helst ... eller ingenting
  52. 52. Vad är sant och falskt i JavaScript?
  53. 53. Truthiness is a ”truth” that a person claims toknow intuitively ”from the gut” or because it ”feelsright” without regard to evidence, logic, intellectualexamination, or facts. http://en.wikipedia.org/wiki/Truthiness
  54. 54. JavaScript Låt oss testa log = console.log; if(!false) { log("false"); } if(!"false") { log(""false""); } if(!0) { log("0"); } if(!-1) { log("-1"); } if(!"") { log(""""); } if(!null) { log("null"); } if(!undefined) { log("undefined"); } if(![]) { log("[]"); } if(!{}) { log("{}"); }
  55. 55. Hur kan denna falskhet drabba oss?
  56. 56. Först ett par saker …JavaScript JW.obj = {drinks: "coffee"}; JW.obj.drinks; => "coffee" JW.obj["drinks"]; => "coffee" Objekts properties (≈medlemsvariabler) går att komma åt som array-referenser
  57. 57. Först ett par saker …JavaScript o = JW.obj; o.toString; // Finns o.hasOwnProperty(”drinks”) ? o.hasOwnProperty(”toString”) ?
  58. 58. JavaScript Vad gör koden? JW = {}; JW.apply=function(applyTo,applyWith){ for(var prop in applyWith) { if(applyWith.hasOwnProperty(prop) && !applyTo[prop]) { applyTo[prop] = applyWith[prop]; } } } JW.obj = {preselected: 3}; JW.apply(JW.obj,{country: Sweden});
  59. 59. JavaScript Ser ni buggen? JW = {}; JW.apply=function(applyTo,applyWith){ for(var prop in applyWith) { if(applyWith.hasOwnProperty(prop) && !applyTo[prop]) { applyTo[prop] = applyWith[prop]; } } } JW.obj = {preselected: 3}; JW.apply(JW.obj,{country: Sweden});
  60. 60. JavaScript Ser ni buggen? JW = {}; JW.apply=function(applyTo,applyWith){ for(var prop in applyWith) { if(applyWith.hasOwnProperty(prop) && !applyTo[prop]) { applyTo[prop] = applyWith[prop]; } } } JW.obj = {preselected: 0}; JW.apply(JW.obj,{preselected: 5});
  61. 61. Hur startar man ettJavaScript-program?
  62. 62. <html> JavaScript och webb<head> <script src=”js/main.js”></script> <script> var JW = {}; // Mer kod </script></head><body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  63. 63. <html> JavaScript och webb<head> Skript från fil i <head> <script src=”js/main.js”></script> <script> var JW = {}; // Mer kod </script></head><body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  64. 64. <html> JavaScript och webb<head> Skript från fil i <head> <script src=”js/main.js”></script> <script> var JW = {}; Inline:at skript i <head> // Mer kod </script></head><body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  65. 65. <html> JavaScript och webb<head> Skript från fil i <head> <script src=”js/main.js”></script> <script> var JW = {}; Inline:at skript i <head> // Mer kod </script></head> Skript, direkt i HTML<body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  66. 66. <html> JavaScript och webb<head> Skript från fil i <head> <script src=”js/main.js”></script> <script> var JW = {}; Inline:at skript i <head> // Mer kod </script></head> Skript, direkt i HTML<body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> Inline:at skript i <body> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  67. 67. <html> JavaScript och webb<head> Skript från fil i <head> <script src=”js/main.js”></script> <script> var JW = {}; Inline:at skript i <head> // Mer kod </script></head> Skript, direkt i HTML<body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> Inline:at skript i <body> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html> Skript från fil i <body>
  68. 68. <html> Laddning och körning<head> <script src=”js/main.js”></script> <script> var JW = {}; // Mer kod </script></head><body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  69. 69. <html> Laddning och körning<head> Synkron laddning och körning <script src=”js/main.js”></script> <script> var JW = {}; // Mer kod </script></head><body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  70. 70. <html> Laddning och körning<head> Synkron laddning och körning <script src=”js/main.js”></script> <script> var JW = {}; Körs synkront, dvs innan // Mer kod </script> DOM:en har laddats</head><body> <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  71. 71. <html> Laddning och körning<head> Synkron laddning och körning <script src=”js/main.js”></script> <script> var JW = {}; Körs synkront, dvs innan // Mer kod </script> DOM:en har laddats</head><body> Körs vid klick-eventet <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  72. 72. <html> Laddning och körning<head> Synkron laddning och körning <script src=”js/main.js”></script> <script> var JW = {}; Körs synkront, dvs innan // Mer kod </script> DOM:en har laddats</head><body> Körs vid klick-eventet <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> Körs när parsern kommit hit <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html>
  73. 73. <html> Laddning och körning<head> Synkron laddning och körning <script src=”js/main.js”></script> <script> var JW = {}; Körs synkront, dvs innan // Mer kod </script> DOM:en har laddats</head><body> Körs vid klick-eventet <button onclick="document.getElementById(field2).value=document.getElementById(field1).value">Kopiera text</button> <div> Lite information </div> Körs när parsern kommit hit <script> JW.calcPrice = function(price, vat) { //… }; </script> <script src=”http://3rdparty.com/trackUsers.js”></script></body></html> Laddas och körs synkront
  74. 74. Asynkron laddning(function(){ var oldFirstScript = document.getElementsByTagName(script)[0]; newScript = document.createElement(script), newScript.async = true; newScript.src = js/script.js; oldFirstScript.parentNode.insertBefore( newScript, oldFirstScript);}());
  75. 75. Synkron, blockerande laddning<script src=”js/script.js”></script> KörLaddaHtmlAsynkron, icke-blockerande laddning<script defer src=”js/script.js”></script> KörLaddaHtmlAsynkron, blockerande laddning<script async src=”js/script.js”></script> KörLaddaHtml
  76. 76. Synkron, blockerande laddning<script src=”js/script.js”></script> KörLaddaHtmlAsynkron, icke-blockerande laddning<script defer src=”js/script.js”></script> KörLaddaHtmlAsynkron, blockerande laddning<script async src=”js/script.js”></script> KörLaddaHtml
  77. 77. Synkron, blockerande laddning<script src=”js/script.js”></script> KörLaddaHtmlAsynkron, icke-blockerande laddning<script defer src=”js/script.js”></script> KörLaddaHtmlAsynkron, blockerande laddning<script async src=”js/script.js”></script> KörLaddaHtml
  78. 78. OK, men hur startar vi?
  79. 79. Java In the Beginningpublic static void main(String[] args)JavaScript (function(){}()); window.someGlobalFunction();
  80. 80. Självinvokerande funktionerAnonym, självinvokerande med parameter(function myFunc(me) { // Kod}(John));Anonym, självinvokerande utan parameter(function myFunc() { // Kod}());
  81. 81. Självinvokerande funktionerAnonym, namnlös och självinvokerande(function() { // Kod}());Namngiven, självinvokerande, icke-anropsbarvar myFunc = function(me) { // Kod}(John);
  82. 82. Variabler
  83. 83. JavaScript Scope var GLOB = {}; GLOB.func = function(array) { var local = …; … for (var i=0; i<array.length; i++){ … var temp = array[i]; } };
  84. 84. JavaScript Scope var GLOB = {}; GLOB.func = function(array) { var local = …, i, temp; … for (i=0; i<array.length; i++){ … temp = array[i]; } };
  85. 85. JavaScript Scope var GLOB = {}; GLOB.func = function(array) { var local = …, i, temp; … for (i=0; Det finns bara två variabel-scope: i<array.length; i++){ … Globalt eller lokalt funktions-scope. temp = array[i]; } Alla lokala variabler ”hissas” till }; toppen av funktionen (hoisting).
  86. 86. Statiska variabler?Medlemsvariabler?
  87. 87. JavaScript JW.Personnummer = function (personnummerStr) { this.personnummer = personnummerStr; var checksum = personnummerStr.substring(11,12); }; JW.Personnummer.prototype.regexp = /[0-9]+/; JW.Personnummer.OLDEST_DATE = new Date(1880, 0, 1); JW.obj = new JW.Personnummer("191212121212"); JW.obj.personnummer; JW.obj.checksum; JW.obj.regexp; JW.Personnummer.OLDEST_DATE
  88. 88. JavaScript JW.Personnummer = function (personnummerStr) { this.personnummer = personnummerStr; var checksum = personnummerStr.substring(11,12); }; JW.Personnummer.prototype.regexp = /[0-9]+/; JW.Personnummer.OLDEST_DATE = new Date(1880, 0, 1); JW.obj = new JW.Personnummer("191212121212"); JW.obj.personnummer; JW.obj.checksum; JW.obj.regexp; JW.Personnummer.OLDEST_DATE
  89. 89. JavaScript JW.Personnummer = function (personnummerStr) { this.personnummer = personnummerStr; var checksum = personnummerStr.substring(11,12); }; JW.Personnummer.prototype.regexp = /[0-9]+/; JW.Personnummer.OLDEST_DATE = new Date(1880, 0, 1); JW.obj = new JW.Personnummer("191212121212"); JW.obj.personnummer; JW.obj.checksum; JW.obj.regexp; JW.Personnummer.OLDEST_DATE
  90. 90. JavaScript JW.Personnummer = function (personnummerStr) { this.personnummer = personnummerStr; var checksum = personnummerStr.substring(11,12); }; JW.Personnummer.prototype.regexp = /[0-9]+/; JW.Personnummer.OLDEST_DATE = new Date(1880, 0, 1); JW.obj = new JW.Personnummer("191212121212"); JW.obj.personnummer; JW.obj.checksum; JW.obj.regexp; JW.Personnummer.OLDEST_DATE
  91. 91. JavaScript JW.Personnummer = function (personnummerStr) { this.personnummer = personnummerStr; var checksum = personnummerStr.substring(11,12); }; JW.Personnummer.prototype.regexp = /[0-9]+/; JW.Personnummer.OLDEST_DATE = new Date(1880, 0, 1); JW.obj = new JW.Personnummer("191212121212"); JW.obj.personnummer; JW.obj.checksum; JW.obj.regexp; JW.Personnummer.OLDEST_DATE;
  92. 92. JavaScript Closure (hölje) (function(array) { var i, temp; … for (i=0; i<array.length; i++){ … temp = array[i]; } }([1, 2, 3]));
  93. 93. JavaScript Closure (hölje) (function(array) { var i, temp; … for (i=0; i<array.length; i++){ … Ett closure håller sitt scope och sin temp =kontext under hela sin livslängd. array[i]; } }([1, 2, 3])); En referens som kommit innanför höljet (array i exemplet) lever alltså kvar och håller sitt värde inom ”höljet”.
  94. 94. JavaScript Closure-exempel for(i=0; i<pages.length; i++) { var page = pages[i]; pageElement.load(page.url, function() { launchForm(page.form); }); }
  95. 95. JavaScript Closure-exempel for(i=0; i<pages.length; i++) { var page = pages[i]; pageElement.load(page.url, function() { launchForm(page.form); }); Callback-funktion eftersom } pageElement.load() är asynkron
  96. 96. JavaScript Closure-exempel for(i=0; i<pages.length; i++) { var page = pages[i]; pageElement.load(page.url, function() { page hissas och får alltså ett launchForm(page.form); }); nytt värde för varje iteration }
  97. 97. JavaScript Closure-exempel var page; for(i=0; i<pages.length; i++) { page = pages[i]; pageElement.load(page.url, page hissas och får alltså ett function() { nytt värde för varje iteration launchForm(page.form); }); }
  98. 98. JavaScript Closure-exempel var page; for(i=0; i<pages.length; i++) { page = pages[i]; pageElement.load(page.url, function() { launchForm(page.form); }); När väl callbacken anropas så } kommer page referera till pages[pages.length-1] eller åtminstone ett annat element än det var tänkt.
  99. 99. JavaScript Closure-exempel var page; for(i=0; i<pages.length; i++) { page = pages[i]; pageElement.load(page.url, function() { launchForm(page.form); }); }
  100. 100. JavaScript Closure-exempel var page; for(i=0; i<pages.length; i++) { page = pages[i]; (function(page) { pageElement.load(page.url, function() { launchForm(page.form); } }); })(page); }
  101. 101. JavaScript Closure-exempel var page; for(i=0; i<pages.length; i++) { page = pages[i]; (function(page) { pageElement.load(page.url, function() { launchForm(page.form); } Vi binder page till ett nytt hölje }); })(page); så att callbacken refererar rätt }
  102. 102. JavaScript Closure-exempel var page; for(i=0; i<pages.length; i++) { page = pages[i]; (function(myPage) { pageElement.load(myPage.url, function() { launchForm(myPage.form); } Om man mår dåligt av sånt }); så kan man döpa om höljets })(page); variabel :) }
  103. 103. Med självinvokerande funktioner, scope och closures är vi redo för det viktigaste designmönstret:Crockford-modulen eller Module Pattern
  104. 104. JavaScript JW.cache = (function(){}());
  105. 105. JavaScript JW.cache = (function(){ return {}; }());
  106. 106. JavaScript JW.cache = (function(){ return { getPatient: function(personnummer) { } }; }());
  107. 107. JavaScript JW.cache = (function(){ var cache = {}; return { getPatient: function(personnummer) { } }; }());
  108. 108. JavaScript JW.cache = (function(){ var cache = {}; return { getPatient: function(personnummer) { var res=cache[personnummer]; // Check if fresh // Return } }; }());
  109. 109. JavaScript JW.cache = (function(){ var cache = {}; return { getPatient: function(personnummer) { var res=cache[personnummer]; if(_isValid(res)) { return res.patient; } else { // Handle cache miss } } }; }());
  110. 110. JavaScript JW.cache = (function(){ var cache = {}, _isValid = function(res) { } return { getPatient: function(personnummer) { var res=cache[personnummer]; if(_isValid(res)) { return res.patient; } else { // Handle cache miss } }
  111. 111. JavaScript JW.cache = (function(){ var cache = {}, _isValid(res) { return !res ? false : (Date.now() - res.timestamp) <= 60000; // One minute } return { getPatient: function(personnummer) { var res=cache[personnummer]; if(_isValid(res)) { return res.patient; } else { // Handle cache miss
  112. 112. JavaScript JW.cache = (function(){ var cache = {}, _isValid(res) { return !res ? false : (Date.now() - res.timestamp) <= 60000; // One minute } return { Vi kan alltså ha (closure-)privata variabler och funktioner getPatient: function(personnummer) { var res=cache[personnummer]; if(_isValid(res)) { return res.patient; } else { // Handle cache miss
  113. 113. JavaScript Crockford = (function(initParam) { var privVar1, privVar2, _privFunc1 = function() { }, _privFunc2 = function() { }; return { pubVar1: ”value”, pubFunc1: function() { } }; }(initParam));
  114. 114. För att möjliggöra enhetstester använder man någon form av Revealing Module Pattern
  115. 115. JavaScript Crockford = (function(initParam) { var _privFunc = function() { }; return { unitTestHandle: { privFunc: _privFunc } }; }(initParam));
  116. 116. JavaScript Crockford = (function(initParam) { var _privFunc = function() { }; return { unitTestHandle: { privFunc: function() { log(”Only use in unit test”); return _privFunc(); } } }; }(initParam));
  117. 117. Namngivna parametrar
  118. 118. Java Metodsignaturerpublic void execPurchase(int, String,String, boolean, User)JavaScript function execPurchase(price, item, discountCode, wantsSpam, user)
  119. 119. Java Metodsignaturerbuilder = new Purchase.Builder();Purchase purchase = builder.setPrice(9900) .setItem(”keps”).wantsSpam(false) .setUser(user).build();JavaScript function execPurchase(purchase) { purchase.price … purchase.item … purchase.wantsSpam … purchase.user …
  120. 120. Vad innebär ettJavaScript-bygge?
  121. 121. JavaScript-bygge• Hantering av ramverk och bibliotek• Beroendehantering egna filer/moduler/ klasser• Enhetstester och statisk analys• Konkatenering och minifiering• final.html
  122. 122. Hantering av ramverk• Vill ofta cache:a tredjepartsbibliotek hårt• Ibland hotlink:a till CDN eller dylikt• Därför sällan slå ihop med egen kod• Vill sällan ha i sitt eget repo
  123. 123. Beroendehantering egen kod• AMD – Asynchronous Module Definition• Bundlat i större ramverk såsom YUI och Ext JS• Fristående require.js m.fl.
  124. 124. Enhetstester och statisk analys• Enhetstester med Jasmine, JSTestDriver etc.• phantom.js – webbläsare utan GUI• sinon.js – mockramverk• Statisk analys med JSHint eller JSLint
  125. 125. Konkatenering och minifiering• Google Closure Compiler• YUI Compressor• uglify.js• require.js utför konkatenering och minifiering med Closure Compiler och uglify.js
  126. 126. Utan beroendehanteringHTML<head> <link rel="stylesheet" type="text/css" href="css/main.css"> <script src="js/lib/jquery-1.7.1.min.js"></script> <script src="js/lib/jquery-encoder-0.1.0.js"></script> <script src="js/base.js"></script> <script src="js/JW/util/util.js"></script> <script src="js/JW/personnummer/Personnummer.js"></script> <script src="js/JW/patient/Patient.js"></script> <script src="js/JW/cache/cache.js"></script> <script src="js/JW/proxy/proxy.js"></script> <script src="js/JW/gui/gui.js"></script></head>
  127. 127. Med beroendehanteringHTML<head> <link rel="stylesheet" type="text/css" href="css/main.css"> <script data-main="js/base" src="js/lib/require-1.0.5/require.js"></script></head>
  128. 128. java -classpath /path/to/rhino/js.jar:/path/to/Closure_Compiler/compiler.jarorg.mozilla.javascript.tools.shell.Main ../../r.js -o name=baseout=min.js baseUrl=.paths.jquery=empty: paths.jquery-encoder=empty:
  129. 129. final.htmlHTML<head> <link rel="stylesheet" type="text/css" href="css/main.css"> <script src="js/lib/require-1.0.5/require.js"></script> <script> require.config({ paths: { "base": "js/min", "jquery": "js/lib/jquery-1.7.1.min", "jquery-encoder": "js/lib/jquery-encoder-0.1.0" } }); require(["base"]); </script></head>
  130. 130. Några extras
  131. 131. Strict Mode (ES5)• Inled JavaScript-fil eller funktions-scope med ”use strict”;• Omöjliggör ofrivilliga globala variabler• Inget läckage av globala objektet till this• Omöjliggör”keps”,i objekt à la { item: duplikat item: ”boll”}• Ingen skuggning via eval(”var x;”)
  132. 132. JavaScript seal (ES5) JW = {name: "John"}; JW.name = "Joe"; JW.job = "coder"; console.log(JW.name + ", " + JW.job);
  133. 133. JavaScript seal (ES5) JW = {name: "John"}; Object.seal(JW); JW.name = "Joe"; JW.job = "coder"; console.log(JW.name + ", " + JW.job);
  134. 134. JavaScript freeze (ES5) JW = {name: "John"}; Object.freeze(JW); JW.name = "Joe"; JW.job = "coder"; console.log(JW.name + ", " + JW.job);
  135. 135. JavaScript freeze (ES5) JW = {name: "John"}; Men … obj.prototype kan Object.freeze(JW); fortfarande ändra på förseglade och frysta JW.name = "Joe";testat att frysa prototypen objekt. Jag har JW.job =det verkar fungera men det måste och "coder"; förstås analyseras för sidoeffekter. console.log(JW.name + ", " + JW.job);
  136. 136. JavaScript arguments JW = function() { console.log(arguments.length); for(var i=0; i<arguments.length; i++) { console.log(arguments[i]); } return "done"; } JW(1, "Joe", [2, 3, 4]);
  137. 137. Referensdokumentation Alltid developer.mozilla.org Aldrig www.w3schools.com Varför? w3fools.com
  138. 138. jsfiddle.net
  139. 139. Att följa http://javascriptweekly.com/ @javascript_news@BrendanEich @littlecalculist@addy_osmani @addyosmani @paul_irish @badass_js @rwaldron @slicknet @kangax @unscriptable @sthlmjs

×