javascript fundamentals for php developers

Post on 06-May-2015

797 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

Javascript fundamentals from a PHP developers' point of view. Compares some of the principles of javascript with their php counterpart. Introduces a way to build simple robust modules in Javascript. You can view the source of the slides (html+js) here: https://bitbucket.org/chrisramakers/talk-javascript-for-php-developers

TRANSCRIPT

JAVASCRIPT FUNDAMENTALSFOR PHP DEVELOPERS

@chrisramakersNovember 2013 PHPBenelux Usergroup Meeting

WHO AM I?@chrisramakersZend Certified PHP EngineerSoftware Engineer @ NucleusFront- and backend developmentBuilding RESTFUL API'sIntegrating them with AngularJS

WHAT ABOUT YOU?Never used JavascriptIntermediate JavascriptJavascript expert

WHAT IS THIS TALK ABOUT?I can hear you "I know Javascript! Booooring!"

I'm not a guru either but I have a lot of experience.So I'm going to share some of it with you.

HistoryJavascript BootcampWriting modulesWhat will the future bring?

JAVASCRIPT HISTORY

JAVASCRIPT HISTORYInterpreted scripting languageObject oriented but not Class basedMost popular language on GithubDeveloped at Netscape in 1995Around the same time as PHP (1997)First called LiveScript, then renamed JavascriptStandardised as ECMAScript (ECMA-262) in 1997Other implementations

Serverside: Netscape Enterprise Server, Node.JS,Databases: CouchDB, MongoDB, Riak, ...CoffeescriptAdobe: ExtendScript, Actionscript,

IT'S EVEN A POWERPOINT REPLACEMENT!These slides are built with reveal.js

Check it out: lab.hakim.se/reveal-js

WE KNEW JAVASCRIPT LIKE THIS

Note: This is a screenshot, not a real error!!! :D

AND THIS

SIGH

BUT WE COULD DO STUFF LIKE THIS TOOfunction trollolololl() { window.open(self.location, '');}window.onload = trollolololl;

And feel like a real hacker :)note: this no longer works

HOW WE KNOW JAVASCRIPTA lot has changed, there are many high quality libraries and tools available.

But we are not going to talk about that ...

JAVASCRIPT BOOTCAMP!

OPERATORSTHE BASIC BUNCH

Assignment operators = += -= *= ...Arithmic operators + - / *Bitwise operators >> << & ̂ | ~Comparison operators == != === !== > >= < <=Logical operators || && !

Look familiar no?

OPERATORS CONTINUED ...concatoperator +

concatenates 2 strings

in -operator determines if the left operant is a property of the rightoperant

delete removes a property from an object

typeof returns the data type of an object

instanceof determines of the left operant is of the the right operantobject type

And more like new, this, ...Again most of these should look familiar.

DATA TYPES PHP JavascriptPrimitives string

integerfloatboolean

StringNumberBoolean

Compound arrayobject

ArrayObject

Special resourcenull

undefinednull

THE GLOBAL OBJECTSomething like $GLOBALS inphpAccessible everywherewindow-object in browsers

3 GLOBAL PROPERTIESNaNInfinityundefined

9 GLOBAL FUNCTIONSJavascript PHPparseInt() intval()parseFloat() floatval()isNaN() is_nan()isFinite() is_finite()encodeURIComponent() urlencode()decodeURIComponent() urldecode()encodeURI() ??decodeURI() ??eval() eval()

9 GLOBAL CONSTRUCTORSNot the same as constructors in PHP

String()Number()Boolean()Array()Object()Error()RegExp()Date()Function()

IMMUTABLEAll constructors are immutable Objects

String.prototype.append = function(val){ this = this + val;}

var a = 'Foo';var b = a.append('Bar');

ReferenceError: Invalid left-hand side in assignment

LITERALS AND CONSTRUCTORSWe don't need constructors ... we got literals!

Literal Constructor

String "Nucleus" new String("Nucleus");

Boolean true new Boolean(true);

Array ['a', 'a']; new Array('a', 'b');

Objects { a : 'b' } new Object();

Number 1.23; new Number(1.23);

RegExp /[A-Z]/i; new RegExp('[A-Z]', 'i');

Function function(x){ return x+1; }; new Function('x', 'return x+1;');

Date There is no Date literal new Date(2013, 11, 23);

RELATION BETWEEN LITERALS AND CONSTRUCTORSvar a = "foobar";var b = a.toUpperCase();alert(b); // Alerts "FOOBAR"

Constructors wrap literals internallyJavascript internally converts primitives to their object counterpartCauses some really funky behaviour!WTFPM++

AND NOW THE "FUN" BEGINS ...TYPEOF

typeof 'foo'; // "string"

typeof String; // "function"

typeof String(); // "string"

var s = new String('foo');typeof s // "object"

INSTANCEOFvar foo = new String('foo');var bar = 'bar';

foo instanceof String; // truebar instanceof String; // false

Wait ... it gets better :)

var boys = new Array('Joe', 'Bob');var girls = ['Jane', 'Alice'];

boys instanceof Array; // truegirls instanceof Array; // true

instanceof on navite data types is not reliable!use jQuery.type(), angular.isString(), ...

ERRORS AND ERROR HANDLINGPHP Javascript

try { ... } catch(e) { ... } try { ... } catch(e) { ... }

throw new Exception(msg, code); throw 'Something went wrong!';

throw 500;

throw 'up';

throw {message: 'foo', code: 500};

throw new Error('up');

SCOPEScope refers to where a variable or functions are accessible

and in what context they are being manipulated.

There 2 types of scope

GlobalLocal

Basically it means it's attached to the window object which is the topmostobject.

GLOBAL SCOPEWhen something is in the global scope

it means that it is accessible from anywhere in your code.

var foo = "Nucleus";function bar(){ alert(foo);}

bar(); // alerts 'Nucleus'alert(foo) // also alerts 'Nucleus'alert(window.foo) // again alerts 'Nucleus'

LOCAL SCOPEWhen something is in the local scope it means it's only available in the

containing function and all functions defined at the same level or deeper.

function bar(){ var foo = "Nucleus"; alert(foo);}

bar(); // alerts 'Nucleus'alert(foo) // error: foo is not definedalert(window.foo) // error: foo is not defined

CLOSURESA closure is an expression (typically a function) that can have

variables together with an environment that binds those variables(that "closes" the expression).

PHP CLOSURESIn PHP closures are most commonly called 'anonymous functions' and are

implemented using the Closure class.

// PHP Closure$foo = function() { return 'Nucleus';};echo $foo(); // outputs 'Nucleus'echo get_class($foo); // outputs 'Closure'

PHP CLOSURES AND SCOPE$foo = 'Nucleus';$bar = function() { return $foo;};echo $bar(); // PHP Notice: Undefined variable $foo

We need the 'use' construct.

$foo = 'Nucleus';$bar = function() use ($foo) { // added 'use' construct return $foo;};echo $foo(); // Outputs 'Nucleus'

JAVASCRIPT CLOSURESWhenever you see a function, wrapped within another function, a closure is

created and the inner function has access to all variables defined in the outerfunction.

JAVASCRIPT CLOSURES

Outside the greet() function, there is no way to access the prefixvariable.

Only functions defined within the greet() function have access to thisvariable, same goes for the who argument which is also contained within the

closure.

// outer functionfunction greet(who) { var prefix = 'Welcome at '; // Inner function function output(suffix) { alert(prefix + who + suffix); }; output('!');}greet('Nucleus'); // Alerts 'Welcome at Nucleus!'

CLOSURES IN JAVASCRIPTNow we can modify the code to return the inner function.

function greet(who) { var prefix = 'Hello '; var f = function(suffix) { alert(prefix + who + suffix); }; return f;}var joeGreeter = greet('joe');joeGreeter('?'); // Alerts 'Hello joe?'joeGreeter.prefix; // undefined

This way we receive an executable function from the greet() call, but we still have no way to modify the value of prefix.

Looks a lot like private variables in PHP

CLOSURES IN JAVASCRIPTLets add an accessor and mutator (getter and setter).

function greet(who) { var prefix = 'Hello '; var f = function(suffix) { alert(prefix + who + suffix); }; f.setPrefix = function(p){ prefix = p; } f.getPrefix = function(){ return prefix; } return f;}var joeGreeter = greet('joe');joeGreeter('?'); // Alerts 'Hello joe?'

joeGreeter.setPrefix('Hey '); // joe is deaf ...joeGreeter('!!!'); // Alerts 'Hey joe!!!'

SELF EXECUTING FUNCTION PATTERN(function() { // ...}());

Also called IIFE or Immediately Invoked Function ExpressionCreates it's own isolated scope without polluting the global scope.Allows us to 'import' variables into the closure without addressing themglobally

(function($, Y) { // ...}(jQuery, YAHOO));

WRITING JAVASCRIPT MODULESLets do something usefull with it now ...

Javascript doesn't know the concept classes (yet)Nor does it have private/public access to propertiesHow do we build a robust module in javascript then?

HELLO DESIGN PATTERNS!Self Executing Function patternModule pattern

LETS BUILD A SIMPLE MODULE

var COUNTER = (function(){ }());

We start with a self-executingfunction to create an isolate scope.

console.log(COUNTER); // undefined

var COUNTER = (function(){ var _counter = 0; var public = {}; return public;}());

BUILDING A MODULENow we have to actually return

something from our self-executingfunction so COUNTER is not

undefined

console.log(COUNTER); // Object {}

var COUNTER = (function(){ var _counter = 0; var public = { increment : function(){ _counter++; }, getValue : function(){ return _counter; } }; return public;}());

BUILDING A MODULEIf we now add some functions topublic, we create a closure inside

the self-executing function.

console.log(COUNTER.geValue()); // 0 COUNTER.increment();console.log(COUNTER.geValue()); // 1console.log(COUNTER._counter); // undefined

var COUNTER = (function(){ var _counter = 0; var format = function(value){ return 'Counter is ' + value; } var public = { increment : function(){ _counter++; }, getValue : function(){ return format(_counter); } }; return public;}());

BUILDING A MODULENow lets add a "private" method to

format the output a little

COUNTER.increment();COUNTER.increment();

console.log(COUNTER.geValue()); // Counter is 2

var COUNTER = (function(){ var _counter = 0; var _format = 'Counter is '; var format = function(value){ return _format + value; } var public = { increment : function(){ _counter++; }, getValue : function(){ return format(_counter); }, setFormat: function(str){ _format = str; } }; return public;}());

BUILDING A MODULEBut we also want to change the

output format of the module. Lets adda "private" property and a "setter".

COUNTER.increment();COUNTER.increment();

console.log(COUNTER.geValue()); // Counter is 2

COUNTER.setFormat('Value = ');console.log(COUNTER.geValue()); // Value = 2

COUNTER._format = "Foobar"console.log(COUNTER.geValue()); // Value = 2

var COUNTER = (function(){ var _container, _counter = 0, _format = 'Counter is '; var format = function(value){ return _format + value; } var public = { // snip... }; var init = function(container){ _container = container; _container.innerHTML = 'Counter ready!'; return public; } return init;}());

BUILDING A MODULENow we want to configure the

module from the outside. The easiestway to that is to add an init

function.

DEMO TIME ...

<div id="container"></div><button id="trigger">Add 1</button>

var c = document.getElementById('container') t = document.getElementById('trigger');

var myCounter = COUNTER(c);t.onclick = function(){ myCounter.increment();};

Counter ready!Add 1

Try it yourself at http://ncl.uz/counterdemo

A LITTLE EXTRA ...What if we need to build a really large module?Spread over several files?

MODULE AUGMENTATION

// module.jsvar COUNTER = (function(){ var _counter = 0; var _format = 'Counter : '; var format = function(value){ return _format + value; } var public = { increment : function(){ _counter++; }, getValue : function(){ return format(_counter); }, setFormat: function(str){ _format = str; } }; return public;}());

AUGMENTING A MODULEWe want to add a new public methodshout to the already existing

COUNTER

// module.shout.jsvar COUNTER = (function(public){ public.shout = function(){ var output = public.getValue(); return output.toUpperCase(); }; return public;}(COUNTER));

Can only access/override the publicAPI

THE BAD PARTS ...Only one instanceNo inheritance systemAugmentation only has access to the public API

THE FUTUREUMD (UNIVERSAL MODULE DEFINITION)

Defines a way to structure modules so they work both in the browser and on the server

github.com/umdjs/umd

AMD (ASYNCHRONOUS MODULE DEFINITION)

Defines a way to load modules in any arbitrary ordergithub.com/amdjs/amdjs-api

TAKING A LOOK AT ECMASCRIPT 6WHAT CAN WE EXPECT FROM ES6?

Current status: kangax.github.io/es5-compat-table/es6

DEFAULT PARAMETERSES5

function increment(x, y) { y = y || 1; return x += y; }

ES6function increment(x, y = 1) { return x += y; }

LEXICAL SCOPE WITH LETES5

function doSomething() { var x = 5; if (someCondition) { var x = 10; doSomethingElse(x); } console.log(x); // 10 !!}

ES6function doSomething() { let x = 5; if (someCondition) { let x = 10; doSomethingElse(x); } console.log(x); // 5 !!}

CONSTANTSES5

// Nope ... no constants for you

ES6const limit = 100;limit = 200; // SyntaxError

CALLBACK ARROW NOTATIONES5

[1,2,3].map(function (x) { return x * x;});

ES6[1,2,3].map(x => x * x);

CLASS DEFINITIONSES5

function Vehicle(color) { this.color = color; this.speed = 0;} Vehicle.prototype.drive = function() { this.speed = 40;}

ES6class Vehicle { constructor(color) { this.color = color; this.speed = 0; } drive() { this.speed = 40; }}

CLASS INHERITANCEES5

function Car(brand, color) { Vehicle.call(this, color); this.brand = brand; this.wheels = 4;} Car.prototype = Object.create(Vehicle.prototype);Car.prototype.constructor = Car;

ES6class Car extends Vehicle { constructor(brand, color) { super(color); this.brand = brand; this.wheels = 4; }}

WRAPPING UP ...You can build pretty robust modules in JavascriptBut they are still not comparable to PHP ClassesWe haven't touched inheritance, interfaces, abstract classes, etc ...These are all possible with Javascript... but that's for another time

QUESTIONS?

THANKS!chris@nucleus.be@chrisramakersAny feedback is appreciated!joind.in/10254Come talk to me!

top related