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
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 dynamisktypning
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
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
JavaScript: Utökning viaprototyp
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());
JavaScript: Utökning viaprototyp
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());
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);
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
Först ett parsaker …
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 parsaker …
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});
<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
Synkron, blockerande laddning
<scriptsrc=”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
<scriptsrc=”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
<scriptsrc=”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
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).
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”.
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.
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
JavaScript-bygge
• Hantering avramverk 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
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;”)
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);