|
|
http://en.wikipedia.org/wiki/JavaScript
JavaScript
var obj = {
name: "String",
"while": "keyword as property name",
flag: true,
root2: 1.414213562,
method: function () {
return new Date();
},
lines: [ 1, 2, "abc" ]
};
Objects are associative arrays
var obj = {}; // new Object() no longer used
obj.prop = 'Jason';
obj['prop'] = 'Bourne';
'prop' in obj; // true
obj.prop = null;
'prop' in obj; // true
delete obj.prop;
'prop' in obj; // false
obj.prop; // undefined
[ 30, 10, "Jason" ]
{ "prop1": "value", "prop2": 1.414213562,
"prop3": null, "prop4": true,
"prop5": [ 30, 10, "Jason" ],
"prop6": { "x": 10, "y": -1 }
}
true
JSON.parse()
and JSON.stringify()
var array = [ 30, 10, "Jason", new Date() ];
array.push({ prop: "Bourne" });
// equiv. w/ push
array[array.length] = "Last Element";
array.length; // 6
array[100]; // undefined -> no Exception!
array[1000] = true;
array.length; // 1001
typeof array; // 'object'
for (e in array)
push
, pop
, slice
, sort
, ...)length
property means max(index)+1false
null
undefined
// BTW: can be changed :-(0
''
// empty stringNaN
// Not a Numberfunction add(arg1, arg2) {
var result = arg1 + arg2;
return result;
}
add(3, 7); // 10
add('Jason', ' Bourne'); // 'Jason Bourne'
add([1, 3], [7, 5]); // '1,37,5'
add.length; // 2
typeof add; // 'function'
function add() {
var i, len, result = 0;
for (i = 0, len = arguments.length; i < len; ++i) {
result += arguments[i];
}
return result;
}
add(3, 7, 4, 6); // 20
add.length; // 0
typeof max; // 'undefined'
typeof min; // 'function'
var max = function (a, b) {
return a > b ? a : b;
};
typeof max; // 'function'
function min(a, b) { return a < b ? a : b; }
function jQuery() { /* ... */ }
jQuery.browser = { /* ... */ };
// used as function
var $info = jQuery('#info');
// used as object (holds ref to trim-function)
jQuery.trim(' hi ');
// click-function gets a function reference
jQuery('#btnOk').click(function () { /* ... */ });
var MYKA = {}; // MYKA = my killer app
MYKA.helper = function () { /* ... */ };
// defining a new module (sub-namespace)
MYKA.module1 = {
init: function () { /* ... */ },
reload: function () {}
};
MYKA.module1.Customer = function (){
// a constructor function
};
(function() {
var local; // not visible outside
function helper() { /* I'm private */ }
// do something
})();
(function() { /* ... */ })();
(function() { /* ... */ }());
var obj1 = {
name: 'Bourne',
getName: function () {return this.name;}
},
obj2 = {
name: 'Wombosi'
},
getName = obj1.getName;
obj1.getName(); // Bourne
getName.call(obj2); // Wombosi
getName(); // undefined
Many ways - too many ways to fall...
|
|
see "Professional JavaScript for Web Developers", Wrox Press
function LatLng(lat, lng) {
this.lat = lat;
this.lng = lng;
}
var myHome = new LatLng(47.8239, 12.0946);
console.log(myHome);
// { lat: 47.8239, lng: 12.0946 }
LatLng.prototype.toString = function () {
return 'LatLng: ' + this.lat + ';' + this.lng;
};
LatLng.prototype.getLat = function () {
return this.lat;
};
LatLng.prototype.getLng = function () {
return this.lng;
};
function POI(lat, lng, name) {
// Constructor Stealing
LatLng.call(this, lat, lng);
this.name = name;
}
POI.prototype = new LatLng(); // not the best way!
// correct constructor pointer
POI.prototype.constructor = POI;
// overrides LatLng::toString
POI.prototype.toString = function () {
return 'POI: ' + this.name
};
// add new method
POI.prototype.getName = function () {
return this.name
};
var saltys = new POI(47.587, -122.378, 'Saltys');
Object.create
methodDoubleMetaphone.java
doublemetaphone.js
See code-snippets/java
commons-codec:commons-codec:1.5
doublemetaphone
for (i = 0; i < 10; ++i) { /* ... */ }
i
is actually window.i
(a property of the global object window
)
var
on top of scope (function)for(var i=0; ...
- this is misleadingconsole.log(typeof a); // 'undefined'
console.log(typeof c); // 'undefined'
a = 'Wombosi';
console.log(typeof a); // 'string'
if (false) {
var a, b; // (!) unreachable code (!)
}
console.log(b); // undefined
console.log(c); // ReferenceError: c is not defined
==
and !=
do type coercion7 == "7" // true
1 == true // true
Solution: use strict equals ===
and !==
7 === "7" // false
1 === true // false
var obj = {
name: 'Jason Bourne',
printLater: function () {
setTimeout(function () {
console.log(this.name);
}, 1000);
}
};
obj.printLater(); // logs undefined
this does not point to obj
!
var obj = {
name: 'Jason Bourne',
printLater: function () {
var self = this; // sometimes that | me
setTimeout(function () {
console.log(self.name);
}, 1000);
}
};
obj.printLater(); // logs Jason Bourne
1/10 + 2/10 // 0.30000000000000004
1 / 0 // Infinity
isFinite(1 / 0) // false
Math.pow(2, 1023) // 8.98846567431158e+307
Math.pow(2, 1024) // Infinity
Number.MAX_VALUE // 1.7976931348623157e+308
parseInt('077') // 63 (!) -> octal value
parseInt('080') // 0 (!) -> parse error
parseInt('080', 10) // 80
parseInt('80abc', 10) // 80 (!)
Number('80abc') // NaN
parseInt('Jason') // NaN
isNaN(Number('Jason')) // true
parseInt(str, 10 /* radix */)
!isNaN(n)
parseInt('ZZ', 36) === 36 * 36 - 1 // true
Number(36 * 36 - 1).toString(36); // 'zz'
return
{
a: true
}
// behaves like ...
return; // = return undefined;
{
a: true
}; // code not reachable -> garbage collected
jQuery.Event = function( src, props ) {
// Allow instantiation without the 'new' keyword
if ( !(this instanceof jQuery.Event) ) {
return new jQuery.Event( src, props );
}
// ...
};
hasOwnProperty
with
- don't ever use it!eval
- be carefulnew Function
- rarly necessary
Demo?
Demo?
/*jshint latedef:true, curly:true*/
a = 'Wombosi';
if (/bos/.test(a))
a += '!';
var a;
Line 4: a += '!';
Expected '{' and instead saw 'a'.
Line 5: var a;
'a' was used before it was defined.
/*global jQuery*/
(function( $ ){
// do something with $
// ($ is local var for global jQuery)
// BTW jQuery is a property of window
})( jQuery );
gjslint
<iframe src="http://jsfiddle.net/..."/>
Poor man's debugger :-;
var a = [1, 9], b = {name: 'Bourne'};
console.log('a', a, 'b', b);
// a [ 1, 9 ] b { name: 'Bourne' }
console.error('No more beer');
Links DailyJS - Mastering Console Logging http://dailyjs.com/2012/02/02/console/ Mozilla Developer Network / console https://developer.mozilla.org/en/DOM/console
if (typeof console === 'undefined') {
(function(global) {
var nop = function(){};
global.console = {
log: nop, info: nop, error: nop,
dir: nop, time: nop, timeEnd: nop
};
}(window));
}
Either ... | ... or? |
---|---|
Real Browser Tests | Phantom.js, Zombie.js, ... |
synchronous | asynchronous |
Unit-Test | Integration-Test |
Browser JS | Rhino, Node, ... |
Manually | Automated |
expect(window.r).to.be(undefined);
expect({ a: 'b' }).to.eql({ a: 'b' })
expect(5).to.be.a('number');
expect([]).to.be.an('array');
expect(window).not.to.be.an(Image);
var callback = sinon.stub();
callback.withArgs(42).returns(1);
callback.withArgs(1).throws("TypeError");
callback(); // No return value, no exception
callback(42); // Returns 1
callback(1); // Throws TypeError
npm
(see node.js slides):$ npm install mocha -g
$ mocha inheritance-test.js
$ mocha --reporter spec *-test.js
$ mocha --watch --growl *-test.js
⇒
use CDATA-Section (recommended)
or
encode <
>
&
with <
>
&
<script type="text/javascript">
// <![CDATA[
if ($.browser.msie &&
parseInt($.browser.version, 10) <= 11) {
alert('Wrong browser!');
}
// ]]>
</script>
Concatenate and minify js files!
Consider using AMD
(function (window, undefined) {
var myString = 'Wombosi';
if (/bos/.test(myString)) {
myString += '!';
}
if (window.wom === undefined) {
window.wom = myString;
}
}(window));
(function(e,t){var n="Wombosi";/bos/.test(n) ↵
&&(n+="!"),e.wom===t&&(e.wom=n)})(window);
$('#menu li').hover(function() {
$(this).toggleClass('hover');
});
$('div.funtimes').animate(
{
left : [ "+=50", "swing" ],
opacity : [ 0.25, "linear" ]
},
300
);
<!DOCTYPE html>
<html lang="en">
<head>
<link href="jquery.mobile-1.1.0.css"
rel="stylesheet"/>
<script src="jquery-1.7.1.js"></script>
<script src="jquery.mobile-1.1.0.js"></script>
<script src="my-application.js"></script>
</head>
<section id="home" data-role="page">
<header data-role="header">
<h1>nerdshow rc</h1>
</header>
<div data-role="content">
<a data-role="button" href="#"
data-icon="arrow-r" id="btn-next">
Next</a>
</div>
</section>
<section id="help" data-role="page">
...
</section>
$('#home').live('pagebeforecreate', function() {
$.mobile.showPageLoadingMsg();
myapp.load(function (error) {
$.mobile.hidePageLoadingMsg();
if (error) {alert(error);}
});
// ...
});
// connect behavior to form elements
$(function () {
$('#btn-next').click(function () {
myapp.nextSlide();
});
});
// my mail address
'hgoebl+goebl.com'.replace('+', '@')
|
|
var i, c = 3,
f = function() { return 2; };
for (i = 1; i <= 3; ++i) {
switch (i) {
case 1: console.log('1'); break;
case f(): console.log('2'); break;
case c: console.log('3'); break;
default: console.log('?'); break;
}
}
try {
fn(); // fn is not defined anywhere
}
catch (e) {
console.log(e); // [ReferenceError: fn is not defined]
console.log(e.type); // not_defined
console.log(e.message); // fn is not defined
}
finally {
console.log('finally');
}
throw {
type: '...',
message: '...'
};
throw Error('Bei mia is ois kabutt');
var i;
console.time('myHeavyLoop');
for (i = 0; i < 100000; i++) {
;
}
console.timeEnd('myHeavyLoop');
// myHeavyLoop: 12ms
var i, nums = [];
for (i = 0; i < 10; i++) {
nums[i] = function (j) {
return i + j;
};
}
nums[0](2); // Prints 12 instead of 2
// example from www.jshint.com/options/
Solution: copy the value of i
var i, nums = [];
for (i = 0; i < 10; i++) {
(function (i) {
nums[i] = function (j) {
return i + j;
}
}(i));
}
// example from www.jshint.com/options/
function f(o) {
if (o && o.prop) {
// use o.prop
}
}
Java is type-safe but more verbose:
public void f(MyObj o) {
if (o != null && o.getProp() != null) {
// use it
}
}
use single var
statement on top of scope
forget about with
forget about eval
check hasOwnProperty
when doing for(e in obj)
use ===
and !==
, avoid ==
and !=
be very careful with (omitting) semicolons
new Array
and new Object