3. Java
Typer
Primitiva:
byte, short, int, long, float, double,
boolean, char
Resten är objekt, s.k. referenstyper
JavaScript
Primitiva:
string, number, boolean, function,
undefined
Resten är object
4. Java
Typer
Primitiva:
byte, short, int, long, float, double,
boolean, char
Resten är objekt, s.k. referenstyper
JavaScript
Primitiva:
string, number, boolean, function,
undefined
Resten är object
5. Java
Typer
Primitiva:
byte, short, int, long, float, double,
boolean, charinte
Strängar är
generella objekt
Resten är objekt, s.k.typ
utan en egen referenstyper
JavaScript
Primitiva:
string, number, boolean, function,
undefined
Resten är object
6. Java
Typer
Primitiva: finns bara en
Det
typ för tal,
byte, short, int, long, float, double,
boolean, char det
oavsett om
är heltal eller
Resten är objekt, s.k. referenstyper
decimaltal
JavaScript
Primitiva:
string, number, boolean, function,
undefined
Resten är object
7. Java
Typer
Primitiva:
byte, short, int, long, float, double,
boolean, char Funktioner är
fullödiga objekt
Resten är objekt, s.k. referenstyper med en egen typ
JavaScript
Primitiva:
string, number, boolean, function,
undefined
Resten är object
8. Java
Typer
Primitiva:
byte, short, int, long, float, double,
boolean, charJavaScripts
version av
Resten oinitialiserad är
är objekt, s.k. referenstyper
JavaScript
undefined
Primitiva:
string, number, boolean, function,
undefined
Resten är object
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. Statisk vs dynamisk typning
Java
Statisk typning:
String name; Variabler har typer
name = ”John”; Värden har typer
name = 34; Variabler kan inte byta typ
JavaScript
Dynamisk typning:
var name; Variabler har inga typer
name = ”John”; Värden har typer
name = 34; Variabler byter typ dynamiskt
19. Johns slutsats
Java är ett statiskt, starkt typat språk
med hyfsat god typsäkerhet
JavaScript är ett dynamiskt, svagt typat språk
med hyfsat god typsäkerhet
32. JavaScript: Utökning via prototyp
JavaScript
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());
36. JavaScript: Utökning via prototyp
JavaScript
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());
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);
53. Truthiness is a ”truth” that a person claims to
know intuitively ”from the gut” or because it ”feels
right” without regard to evidence, logic, intellectual
examination, or facts.
http://en.wikipedia.org/wiki/Truthiness
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. Först ett par saker …
JavaScript
o = JW.obj;
o.toString; // Finns
o.hasOwnProperty(”drinks”) ?
o.hasOwnProperty(”toString”) ?
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. 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. 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});
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. <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. <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. <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. <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. <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. <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. <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. <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. <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. <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. <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
75. Synkron, blockerande laddning
<script src=”js/script.js”></script>
Kör
Ladda
Html
Asynkron, icke-blockerande laddning
<script defer src=”js/script.js”></script>
Kör
Ladda
Html
Asynkron, blockerande laddning
<script async src=”js/script.js”></script>
Kör
Ladda
Html
76. Synkron, blockerande laddning
<script src=”js/script.js”></script>
Kör
Ladda
Html
Asynkron, icke-blockerande laddning
<script defer src=”js/script.js”></script>
Kör
Ladda
Html
Asynkron, blockerande laddning
<script async src=”js/script.js”></script>
Kör
Ladda
Html
77. Synkron, blockerande laddning
<script src=”js/script.js”></script>
Kör
Ladda
Html
Asynkron, icke-blockerande laddning
<script defer src=”js/script.js”></script>
Kör
Ladda
Html
Asynkron, blockerande laddning
<script async src=”js/script.js”></script>
Kör
Ladda
Html
83. JavaScript
Scope
var GLOB = {};
GLOB.func = function(array) {
var local = …;
…
for (var i=0; i<array.length; i++){
…
var temp = array[i];
}
};
84. JavaScript
Scope
var GLOB = {};
GLOB.func = function(array) {
var local = …, i, temp;
…
for (i=0; i<array.length; i++){
…
temp = array[i];
}
};
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).
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. 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. 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. 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. 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. JavaScript
Closure (hölje)
(function(array) {
var i, temp;
…
for (i=0; i<array.length; i++){
…
temp = array[i];
}
}([1, 2, 3]));
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”.
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. 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. 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. 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.
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. 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. Med självinvokerande funktioner,
scope och closures är vi redo för
det viktigaste designmönstret:
Crockford-modulen
eller
Module Pattern
121. JavaScript-bygge
• Hantering av ramverk och bibliotek
• Beroendehantering egna filer/moduler/
klasser
• Enhetstester och statisk analys
• Konkatenering och minifiering
• final.html
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. 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. 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. Konkatenering och
minifiering
• Google Closure Compiler
• YUI Compressor
• uglify.js
• require.js utför konkatenering och
minifiering med Closure Compiler och
uglify.js
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;”)
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);