JavaScriptmake the right choices
Damian Wielgosik
about me ;-)
1. Begin with ECMAScript
ECMAScript
sometimes it’s difficult...
... to speak in a human language
... znaleźć ludzki językDmitry Soshnikov
your personal ECMAScript teacher
Participate in the future!
Harmony - the next ECMAScript standard
mail-archive.com/[email protected]/info.html
2. Know your tools
Yes, we all know Firebug and Web Inspector
Hurt your feelings with jslint.com
Yes, we all know Firebug and Web Inspector
Aardwolf - mobile debugging made easy
Memory stats?
Memory?
WebKit Inspector
Memory leaks?
Memory leak checker
Performance?
sIEeve
home.orange.nl/jsrosman/
Memory leaks?
people.mozilla.com/~dbaron/leak-screencasts/
Performance?
var start = +new Date();for (var i = 0; i < 100000; i++);console.log("Result is: ", +new Date() - start);
Better?
console.time("My test"); for (var i = 0; i < 100000; i++); console.timeEnd("My test");
Still better?
console.profile("My test"); runApp();console.profileEnd("My test");
The best?
jsperf.com
jsperf.com
jsperf measures operations per second!
Get rid of jQuery if it’s not neccessary - there is http://microjs.com
Hunt on new stuff!
3. Tips and tricks
it has to be said...
do not optimize prematurely!
do not optimize prematurely!
flickr.com/photos/paulmartincampbell/3583176306/sizes/o/in/photostream/
JavaScript !== Java
var obj = {}; // not new Object()var arr = []; // not new Array();
forget about your old habits!
do not port bad solutions to JavaScript!(aka I don’t need yet another class system in JS)
otherwise they’re gonna find you! ;-)
http://www.fotofaza.pl/podglad_zdjecia,15,ludzie,chuligani.html
4. Real tips and tricks
function calls cost time!
use JS asynchronously when needed
var arr = [ function() { console.log("A"); }, function() { throw new Error("boom!"); }, function() { console.log("B"); }, function() { console.log("C"); } ];
for (var i = 0, ilen = arr.length; i < ilen; i++) { arr[i]();}
oops?
var arr = [ function() { console.log("A"); }, function() { throw new Error("boom!"); }, function() { console.log("B"); }, function() { console.log("C"); } ];
for (var i = 0, ilen = arr.length; i < ilen; i++) { window.setTimeout(arr[i], 0);}
more interesting results
var fn = function() { console.log("a"); fn();};fn();
stack overflow?
let’s write own scheduler
var scheduler;(function() { var events = []; scheduler = { add : function(fn, delay) { for (var i = 0, ilen = events.length; i < ilen; i++) { if (events[i].fn === fn) { throw new Error("The event exists in the main event loop"); } } events.push({ fn : fn, delay: delay }); }, run: function() { for (var i = 0, ilen = events.length; i < ilen; i++) { (function(callback, delay) { var fn = function() { callback(); window.setTimeout(fn, delay); }; window.setTimeout(fn, delay); })(events[i].fn, events[i].delay); } } };})();
scheduler.add(function() { console.log("A"); }, 500); // it will call a function every 500msscheduler.add(function() { console.log("B"); }, 1000); // like above with 1000ms delayscheduler.run();
one loop to handle similar events
var eventLoop;(function() { var events = {}; eventLoop = { add : function(fn, delay) { if (!(delay in events)) { events[delay] = []; } else { for (var i = 0, ilen = events[delay].length; i < ilen; i++) { if (events[delay][i].fn === fn) { throw new Error("The event exists in the main event loop"); } } } events[delay].push(fn); }, run: function() { for (var delay in events) { (function(stack, delay) { var fn = function() { for (var i = 0, ilen = stack.length; i < ilen; i++) { stack[i](); } window.setTimeout(fn, delay); }; window.setTimeout(fn, delay); })(events[delay], delay); } } };})();
eventLoop.add(function() { console.log("A"); }, 500);eventLoop.add(function() { console.log("B"); }, 500);eventLoop.run();
var eventLoop;(function() { var events = {}; eventLoop = { add : function(fn, delay) { if (!(delay in events)) { events[delay] = []; } else { for (var i = 0, ilen = events[delay].length; i < ilen; i++) { if (events[delay][i].fn === fn) { throw new Error("The event exists in the main event loop"); } } } events[delay].push(fn); }, run: function() { for (var delay in events) { (function(stack, delay) { var fn = function() { for (var i = 0, ilen = stack.length; i < ilen; i++) { stack[i](); } window.setTimeout(fn, delay); }; window.setTimeout(fn, delay); })(events[delay], delay); } } };})();
eventLoop.add(function() { console.log("A"); }, 500);eventLoop.add(function() { console.log("B"); }, 500);eventLoop.run();
we don’t want to end up with big array indexes - we use the object instead of array
we have never added events for this delay so let’s make an array to store them
let’s store a single event by that
yep, you have to implement stop() method
Timers can be useful with AJAX requests
var throttle = function(fn, delay) { var timer = null; return function () { var context = this; var args = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(context, args); }, delay); };};
$('input.username').keypress(throttle(function (event) { // do the Ajax request}, 250));
http://remysharp.com/2010/07/21/throttling-function-calls/
parseInt(„09”) === 0
JS thinks „09” is an octal number because it starts with 0
parseInt(„09”, 10) === 9
However,parseFloat(„09”) === 9
However,parseFloat(„09”) === 9
document.querySelectorAll("div")returns a NodeList
not an array
var nodes = document.querySelectorAll("div");nodes = [].slice.apply(nodes);
However:„Whether the slice function can be applied successfully to a host object is
implementation-dependent.” - ECMAScript
Speaking of which, how to check if it’s an array?
var arr = [];arr instanceof Array;
Really?
var Array = function() {};var arr = [];arr instanceof Array; // FALSE!
Next?
var arr = [];if ("length" in arr) { // we deal with an array}
Really?
var arr = { "length": 2 };if ("length" in arr) { // we deal with an array... wait a moment!}
Next?
var arr = [];if (Object.prototype.toString.call(arr) === "[object Array]") { // Houston, we have an array}
Ok, but well, you can still modify a toString fn...
Object.prototype.toString = function() { return "";};
Here we go... ECMAScript 5!
var arr = [];if (Array.isArray(arr)) { // w00t!}
Hey, I can still replace it with my own stuff!
Array.isArray = function() { return false;}
Cache the most important functions at the very beginning!
(function() { var isArray = Array.isArray;})();
Or.. if you can, use ECMAScript 5 again
Object.defineProperty(Array, "isArray", { writable: false, configurable: false, enumerable: false, value: Array.isArray}); // thx to @marcoos
Hey, what is that ECMAScript 5 actually?
Hey, what is that ECMAScript actually?
Hey, we’re on mobile, do you have something for us?
yes, I can! Oh, I do.
Use window.scrollTo(0, 1) to get rid of the browser address bar on iOS!
/mobile/i.test(navigator.userAgent) && !location.hash && setTimeout(function () { if (!pageYOffset) window.scrollTo(0, 1);}, 1000);
thanks to amazing work by Remy Sharphttp://remysharp.com/2010/08/05/doing-it-right-skipping-
the-iphone-url-bar/
More?
Visit JSNews on Facebook for more awesomenesshttp://tinyurl.com/jsnewspl
or attend Front-Trends 2012 conferencehttp://front-trends.com
http://lanyrd.com/2012/ft2012/
but first of all, be smart and listen to smart people - there is a lot on the web
Thanks!Slides at:
http://varjs.com/make-right-choices
Top Related