javascript primer

33
Javascrip t Primer The brainless dump of a brainless man Adam Hepton @adamhepton 2010-2011, Frogtrade Image by Jeremy Richardson, "Dead Frog" March 25 2006 via Flickr, CC BY-NC-SA 2.0 (http://www.flickr.com/photos/jaded/151806291/)

Upload: adam-hepton

Post on 25-Jan-2015

808 views

Category:

Technology


0 download

DESCRIPTION

When I left Frogtrade, I was asked to provide a presentation on Javascript basics to act as reference material for the PHP developers I left behind. This is that presentation.

TRANSCRIPT

Page 1: Javascript Primer

JavascriptPrimer

The brainless dumpof a brainless man

Adam Hepton@adamhepton

2010-2011, Frogtrade

Image by Jeremy Richardson, "Dead Frog" March 25 2006 via Flickr, CC BY-NC-SA 2.0(http://www.flickr.com/photos/jaded/151806291/)

Page 2: Javascript Primer

Arrays and objects

[] = array{} = objectvar arr = [];var oldSchool = array();var obj = {};var oldObj = new Object();

var filledArr =[0, 1, "two", 3, "four"];

var fullObj = {  "key" : "value",  "innerArray" :   [3, "more", "things"]};This is JSON. Valid JSON uses double-quotes. For everything.

Page 3: Javascript Primer

Getting content

from objects

obj.x vs obj[x]obj.x means property 'x' from objobj[x] means evaluate x, and find the result as a property of obj

var obj = {  "name":"Adam",  "age":30}, fld = 'age';> obj.nameAdam> obj[name]name is not defined> obj.fldfld is not defined> obj[fld]30

Page 4: Javascript Primer

Removing content

from objects

delete vs splicedelete obj[key]array.splice(key, 1)var obj = {"name":"Adam","age":30}, arr = [0, 1, 2, 3, 4];

> delete obj['age']{"name":"Adam"}> obj.splice(0, 1);obj has no method 'splice'> arr.splice(2, 1);[0, 1, 3, 4]> delete arr[1][0, null, 3, 4]> arr.length4

Page 5: Javascript Primer

Does it exist?

typeofCheck that something exists before you try and use it, or execution will break.var obj = {  "name":"Adam",  "hoes":[718,202,901,305],  "myFunc": function(i) {    alert(i);  }};

> var x = obj.func();obj has no method 'func'> typeof obj.funcundefined

Page 6: Javascript Primer

Verifying type

typeof (cont.)var obj = {  "name":"Adam",  "hoes":[718,202,901,305],  "myFunc": function(i) {    alert(i);  }};> typeof obj;object> typeof obj.myFuncfunction> typeof obj.hoesobject> typeof nullobject

Page 7: Javascript Primer

I am not an object!

typeof (cont)> typeof obj ===typeof obj.hoes ===typeof null;true> obj.hoes[718,202,901,305]> Object.prototype .toString.call(obj.hoes);[object Array]> obj.member = null;> typeof obj.memberobject> obj.member &&typeof obj.member =='object'false

Page 8: Javascript Primer

Getting info

about objects

for(var i in obj)To find all the properties of an object, iterate over the object with a for ... invar str = "";for(var i in obj) {  if(typeof obj[i] == "string") {    str += obj[i];  }}alert(string);I don't recommend using this on an array, because it is not very efficient - stick with for(i = 0; i < l; i++) or, better still, while(i--) if you don't care about reverse ordering your array.

Page 9: Javascript Primer

Getting MOAR

info about

objects

indexOfTo find out whether something exists within an array, use indexOf. > arr.indexOf("doesn't exist")-1Except in IE, where support for indexOf on arrays in patchy. You could add a simple version to the prototype, but this will affect a for ... in.

The safest way is to use a helper function - if you have jQuery to hand, use $.inArray: if you don't, then roll your own.

Page 10: Javascript Primer

Accessing framed content

.contentWindowTo access the contents of an iframe, use contentWindow, and then continue your call from within that context. You can only manipulate a contentWindow if it is on the same domain (this includes sub-domains).

var frameObj = document.getElementById('anIframe');var frameBody =frameObj.contentWindow.document.body;frameBody.innerHTML ="Changed HTML";

Page 11: Javascript Primer

Referencing windows

parent.windowTo do something from within an iframe on the page that contains the iframe, use parent. You can only manipulate a parent window if it is on the same domain (this includes sub-domains).parent.update(a_variable);parent.window.update(a_variable);parent.document.getElementById('test').innerHTML ='New Content';$('#test',parent.document).html('New Content');> parent === parent.windowtrue

Page 12: Javascript Primer

Scoping

Why no usey?Scoping is used to ensure variables are only accessible where they should be.(function() {  var private = 666;  var shh = function() {    alert(private);  };  secHole = function(x) {    private += x;  };})();> privateprivate is not defined> shh()shh is not defined> secHole()666

Page 13: Javascript Primer

Revealing Module Pattern

Run that by me...

var test = function() {var _private = 666;var public = 111;var fn = function() {console.log(_private);};return {init: fn,p: public};}();

If it's not in the return, it doesn't exist as far as the rest of the code is concerned

Don't forget to execute the function, or you'll feel very foolish

Page 14: Javascript Primer

Keep it tight, yo

> test.privateprivate is undefined> test.fnfn is undefined> test.publicpublic is undefined> test.init()666> test.p111

var test = function() {var _private = 666;var public = 111;var fn = function() {console.log(_private);};return {init: fn,p: public};}();

Page 15: Javascript Primer

Evaluation Order

Erm, what?var test = function() {  var x = 666;    var fn = function() {    console.log(x);  };  x = 999;  return {init: fn};}();

> test.init()999

Because everything is within a function, normal sequential ordering takes place as soon as the function is run for the first time. Good for inits.

Page 16: Javascript Primer

Calling within

another scope

Who gonna .call?Whenever you invoke a function, the this keyword is used to mean "wherever it was called from", and usually, that means window, or the object where the function sits. You can tell a function to behave as though it was invoked from elsewhere, using .call:window.name = "Thor";function bleh(i) {  console.log([this.name,   Math.sqrt(i)]);}var me = {"name":"Adam"};> bleh(65536);["Thor", 256]> bleh.call(me, 256);["Adam", 16]

Page 17: Javascript Primer

Calling within

another scope (II)

Read the .mapIf .call is used for firing one object into a function, .map is its big brother, used to iterate over an array:function foo(bar) {  return Math.pow(bar, 3);}var nums = [0,1,2,3,4];> foo(5)125> var cub = nums.map(foo);[0, 1, 8, 27, 64]> console.log(nums)[0, 1, 2, 3, 4]Note the ordering difference between .call and .map:func.call(obj, param);arr.map(func);

Page 18: Javascript Primer

Calling within

another scope (III)

.reduce()If you wish to perform a function on all members of an array, and get a single result, .reduce is what you want:function foo(a, b) {  return (a * b) - 4;}var nums = [0,1,2,3,4];> nums.reduce(foo);-164> foo(0, 1)-4> foo(-4, 2)-12> foo(-12, 3)-40> foo(-40, 4)-164

Page 19: Javascript Primer

Calling within

another scope (IV)

.reduce() more

Reduce works by taking the previous value and the current value, but the function can also take the parameters of current index, and the array being worked on itself, should you need them:

arr.reduce(  previous_value,  current_value,  [index,  original_array]);

Page 20: Javascript Primer

InterludeAfter the interlude:

jQuery

http://www.macwhirled.com/bacon.htm

Page 21: Javascript Primer

Getting Started

$To start using jQuery, use $. This is an alias to the jQuery object.To perform jQuery once the page and DOM have loaded (properly loaded, not just body onload loaded), use:$(document).ready( ... );

In Frog's PHP, there is a helper function, html_add_onload, which adds everything within the parameter to a $(document).ready function.

Page 22: Javascript Primer

Selectors

The main use of $$('div');// all divs$('#anID');// an element with an ID of 'anID'$('.frog3');// all elements with a class of 'frog3'$('div a.special');// all links with a class of special that have a parent (any depth) div$('div#container >ul.accordion > li');// All list items that are a child of a UL with class 'accordion', which is a child of a div with class 'container'$('div.post + div.cmmt');// Find all divs with class 'cmmt' that are next to a div with class 'post'

Page 23: Javascript Primer

PsuedoElements

"Suede-o Element: is that something a bit like an element?" - Alistair Gill$('div.post:first');//or :last$('li.song:even'); $('li.song:gt(3)');// or :lt(x)$('form#myForm :input');// all inputs, selects, textareas – anything that can take input $('div#holderdiv:visible');// all visible divs within the holder

Page 24: Javascript Primer

Working with

Selectors

Funsies!$('div.post').each( function() {  alert($(this).height()); });Callback function is within the scope of the element itself - as a DOM reference, not a jQuery object

$('div.post').hide().filter('.blog').show();// find all divs with class 'post', hide them, and if they also have the class 'blog', show them. .filter is a superb method, because you can pass either a selector, or a function in, to get to just the elements you want

Page 25: Javascript Primer

Working with

Selectors (II)

Onesies!$('div.post').has('ul');// find only posts that have a ul$('div.post').not('ul');// find only ones that don't$('div.post, div.article, ul.menu').first();// find the first of any of these selectors$('div#menu').children('ul:first').addClass('main').end().next().addClass('afterMenu');// find the div id of menu, then its first child UL. Add a class of main to it, then go back to the menu. Find its next sibling, and add the class of afterMenu to it

Page 26: Javascript Primer

Manipulating

Selectors

Fonzie!$('div.post:first')  .html('<h1>FIRST</h1>' +  $(this).text());// .html is innerHTML, .text is innerText.  Both getters and setters.

if($('input#cName').val()  = frogBlue") {  $('input#cHex')   .val('#0071b9');  }}// .val is a getter and setter for input fields

Page 27: Javascript Primer

Manipulating

Selectors (II)

Ralph Malph!$('div.post:first')  .addClass('fClass');$('div.post:last')  .removeClass('post');$('div.post.eq(2)')  .toggleClass('frogBlue');

var $fP = $('div.post:first');$fP.append('<h2>END</h2>');$fP.prepend('<h1>1st</h1>');$fP.remove('h2');var $h = $fP.detach('h1');$h.addClass('first')  .prependTo($fP);var $h2 = $h.clone();$h2.removeClass('first')  .insertAfter($h);

Page 28: Javascript Primer

Traversing

Selectors

Ron Howard!var $fP = $('div.post:first');

$fP.next();// or .prev(), can use a selector$fP.siblings('div.post');// look in either direction$fP.children('div.commt');// only one level deep$fP.find('p.commt');// at any arbitrary depth$fP.parent();// find the direct parent - can also use a selector$fP.parents('div.cnt');// at any arbitrary depth upwards$fP.closest('div.hldr');// iterate upwards, stop when found

Page 29: Javascript Primer

Compatibility

with DOM

jQuery obj v DOMvar $fP =$('div.post:first');// jQuery object

var fP = $fP.get(0);// DOM Node

$fP.attr('id') === fP.id; // finds the ID$fP.id === fP.attr('id'); // error

$('div.post').each(  function() {alert(this.id);alert($(this).attr('id')); });

Page 30: Javascript Primer

Browser v FeatureThere are two types of difference between browsers. It's too easy to say, "This is just not working in IE7, so I'll do something for IE7". More often, it's a feature that's different in one (or two) browsers than another, so you should use feature detection, where possible.

$.support gives a nice list of things that are known to be different in certain browsers, so check for that. Also, modernizr.com is helpful, but not used in Frog at the moment.

Browser Differences

output of $.support for Chrome 12

Page 31: Javascript Primer

Optimisation

Familiarisationvar $divs = $('div');Store your selectors, if you use them more than once, and they don't change.

.each is bad! Closures are bad!$('div').each(function() {$(this).addClass('blue');});THE UGLYvar addBlue = function() {$(this).addClass('blue');};$('div').each(addBlue);THE BAD

$('div').addClass('blue');THE GOOD, THE ONLY

Page 32: Javascript Primer

Optimisation

(II)

Just a nature walkAssigning event handlers to lots of elements is wasteful. Add them to the parent element for FUN TIMES.$('#on div.clk')  .bind('click',   function() {$(this).toggleClass('on');});What if we add new ones? What if there are 500 of them?$('#on').bind('click',function(e) {if($(e.target)   .is('div.clk')) {     $(e.target)     .toggleClass('on');   }});

Page 33: Javascript Primer

So Long Suckers!

I hate you all