Slide 1

Slide 1 text

reducing the wat-factor when PHPers write JS JavaScript’s Difficult Concepts Explained Jeff Carouth // @jcarouth // #midwestphp

Slide 2

Slide 2 text

JEFF CAROUTH DEVELOPER AT LIFTOPIA @jcarouth

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

Wat? 0.

Slide 6

Slide 6 text

php var_dump(array() + array()); javascript console.dir([] + []);

Slide 7

Slide 7 text

php var_dump(array() + array()); javascript console.dir([] + []); array(0) { }

Slide 8

Slide 8 text

php var_dump(array() + array()); array(0) { } javascript console.dir([] + []); '' ''

Slide 9

Slide 9 text

WAT? https://www.destroyallsoftware.com/talks/wat

Slide 10

Slide 10 text

Scope 1.

Slide 11

Slide 11 text

global& function

Slide 12

Slide 12 text

foo = "I am a globally-scoped var."; console.log(foo); // > I am a globally-scoped var.

Slide 13

Slide 13 text

foo = "I am a globally-scoped var."; function sayFoo() { console.log(foo); } sayFoo(); // > I am a globally-scoped var.

Slide 14

Slide 14 text

foo = "I am a globally-scoped var."; function sayFoo() { console.log(foo); } function defineFoo() { foo = "I am set in defineFoo()"; } defineFoo(); sayFoo(); // > I am set in defineFoo()

Slide 15

Slide 15 text

i = 25; function countOccurrences(num) { num = num || 1; i += num; } function doSomethingInnocent() { var vals = [1, 2, 3, 4]; for (i = 0; i < vals.length; i++) { console.log(vals[i]); } } countOccurrences(1); // > i = 26 doSomethingInnocent(); // > i = 4

Slide 16

Slide 16 text

foo = "I am a globally-scoped var."; function sayFoo() { console.log(foo); } function defineFoo() { var foo = "I am set in defineFoo()"; } defineFoo(); sayFoo(); // > I am a globally-scoped var.

Slide 17

Slide 17 text

variable hoisting

Slide 18

Slide 18 text

foo = "I am a globally-scoped var."; function sayFoo() { console.log(foo); } function cleverlyDefineFoo() { var bar = "I am bar. " + foo; console.log(foo); var foo = "I am a local foo."; } cleverlyDefineFoo(); sayFoo(); // > I am bar. undefined // > undefined // > I am a globally-scoped var.

Slide 19

Slide 19 text

“private variables”

Slide 20

Slide 20 text

foo = "I am global foo."; function myModule() { function sayFoo() { console.log(foo); } sayFoo(); } myModule(); // > I am a global foo.

Slide 21

Slide 21 text

foo = "I am global foo."; function myModule() { function sayFoo() { var foo; foo = "I am a local variable."; console.log(foo); } sayFoo(); } myModule(); console.log(foo); // > I am a local variable. // > I am global foo.

Slide 22

Slide 22 text

function myModule() { var foo; function sayFoo() { foo = "I am a local variable."; console.log(foo); } sayFoo(); } myModule(); console.log(foo); // > I am a local variable. // > ReferenceError: foo is not defined

Slide 23

Slide 23 text

IIFE&Modules

Slide 24

Slide 24 text

(function() { //do something })();

Slide 25

Slide 25 text

(function() { var foo; function defineFoo() { foo = "I am a local variable."; } defineFoo(); console.log(foo); })(); // > I am a local variable.

Slide 26

Slide 26 text

var module = (function() { var foo; function defineFoo() { foo = { bar: "I am bar.", baz: function() { console.log("I am baz."); } }; } defineFoo(); return foo; })(); console.log(module.bar); // > I am bar. module.baz(); // > I am baz.

Slide 27

Slide 27 text

var counter = (function() { var count = 0; return { increase: function() { count++; return count; }, decrease: function() { count--; return count; } }; })(); console.log(counter.increase()); // 1 console.log(counter.increase()); // 2 console.log(counter.increase()); // 3 console.log(counter.decrease()); // 2 console.log(counter.increase()); // 3 console.log(counter.increase()); // 4 console.log(counter.decrease()); // 3

Slide 28

Slide 28 text

locally-scoped globals

Slide 29

Slide 29 text

var myModule = (function($, _) { return { display: function(a) { _.each(a, console.log); } } })(jQuery, _);

Slide 30

Slide 30 text

Context 2.

Slide 31

Slide 31 text

this PLEASE EXPLAIN

Slide 32

Slide 32 text

counter = 5; $this->doSomethingElse(); } public function doSomethingElse() { // do something } }

Slide 33

Slide 33 text

magicCounter = { count: 0, increaseCount: function() { this.count++; }, decreaseCount: function() { this.count--; } }; console.log(magicCounter.count); // 0 magicCounter.increaseCount(); magicCounter.increaseCount(); console.log(magicCounter.count); // 2 magicCounter.decreaseCount(); console.log(magicCounter.count); // 1

Slide 34

Slide 34 text

count = 0; magicCounter.count = 0; myCounterIncreaser = function(callback) { console.log("Increasing counter."); callback(); callback(); console.log(magicCounter.count); // 0 console.log(this.count); // 2 } myCounterIncreaser(magicCounter.increaseCount); // > Increasing counter. // > 0 // > 2

Slide 35

Slide 35 text

global& function

Slide 36

Slide 36 text

function myFoo() { var bar = "baz"; function something() { console.log(bar); } something(); } myFoo(); // > baz

Slide 37

Slide 37 text

function myFoo() { var bar = "baz"; this.something = function() { console.log(bar); } this.something(); } myFoo(); // > baz

Slide 38

Slide 38 text

function myFoo() { var bar = "baz"; this.something = function() { console.log(bar); } this.something(); } myFoo(); // > baz something(); // > baz

Slide 39

Slide 39 text

function Foo() { var bar = "baz"; this.something = function() { console.log(bar); } this.something(); } myFoo = new Foo(); // > baz something(); // > ReferenceError: something is not defined myFoo.something(); // > baz

Slide 40

Slide 40 text

default context

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

function logContext() { console.log(this); } logContext(); // > Global

Slide 43

Slide 43 text

function contextMagic() { function logContext() { console.log(this); } logContext(); } contextMagic(); // > Global

Slide 44

Slide 44 text

method context

Slide 45

Slide 45 text

contextMethod = { logContext: function() { console.log(this); } }; contextMethod.logContext(); // > Object { logContext: [Function] }

Slide 46

Slide 46 text

contextMethod = { logContext: function() { console.log(this); } }; contextMethod.logContext(); // > Object { logContext: [Function] } var myContextLogger = contextMethod.logContext; myContextLogger(); // > Global

Slide 47

Slide 47 text

.call() & .apply()

Slide 48

Slide 48 text

var foo = { logContext: function() { console.log(this); } }; foo.logContext(); // > Object { logContext: [Function] }

Slide 49

Slide 49 text

var foo = { logContext: function() { console.log(this); } }; foo.logContext(); // > Object { logContext: [Function] } foo.logContext.call(); // > Global

Slide 50

Slide 50 text

var foo = { logContext: function() { console.log(this); } }; foo.logContext(); // > Object { logContext: [Function] } foo.logContext.call(); // > Global foo.logContext.call(this); // > Global

Slide 51

Slide 51 text

var foo = { logContext: function() { console.log(this); } }; foo.logContext(); // > Object { logContext: [Function] } foo.logContext.call(); // > Global foo.logContext.call(this); // > Global var bar = { baz: "fizz" }; foo.logContext.call(bar); // > Object { baz: "fizz" }

Slide 52

Slide 52 text

var fizz = { buzz: function() { for (var i = this.start; i <= this.end; i++) { console.log(i); } } }; var range = { start: 1, end: 3 }; fizz.buzz.call(range); // > 1 // > 2 // > 3

Slide 53

Slide 53 text

var module = { printRange: function(start, end) { console.log(start + ".." + end); } }; var bar = {}; module.printRange.call(bar, 1, 5); // > 1..5 module.printRange.apply(bar, [3, 25]); // > 3..25

Slide 54

Slide 54 text

Objects & Prototypes 3.

Slide 55

Slide 55 text

{}

Slide 56

Slide 56 text

var foo = { bar: "baz", fizz: "buzz", bang: function() { console.log(this.bar + " " + this.fizz); } }; foo.bang(); // > baz buzz

Slide 57

Slide 57 text

functions

Slide 58

Slide 58 text

var logContext = function() { console.log(this); }; console.log(logContext); // > [Function] console.log(typeof logContext); // > function

Slide 59

Slide 59 text

Classes PROTOTYPES

Slide 60

Slide 60 text

var someFunction = function() { console.log(this); }; var obj = new someFunction(); console.log(obj); // > Object [someFunction] // > Object [someFunction]

Slide 61

Slide 61 text

var someFunction = function() { console.log(this); }; var obj = new someFunction(); console.log(obj); // > Object [someFunction] // > Object [someFunction] var SomeFunction = function() { console.log(this); }; var obj = new SomeFunction(); // > Object [SomeFunction]

Slide 62

Slide 62 text

var Car = function() { this.make = "Ford"; this.model = "F150"; this.started = false; this.start = function() { if (this.started) { return; } this.started = true; }; }; var myCar = new Car(); console.log(myCar); // > { make: 'Ford', model: 'F150', started: false, start: ... myCar.start(); console.log(myCar); // > { make: 'Ford', model: 'F150', started: true, start: ...

Slide 63

Slide 63 text

var Car = function(make, model) { this.make = make; this.model = model; this.toString = function() { return this.make + " " + this.model; }; }; var myCar = new Car("Dodge", "Charger"); var wifeCar = new Car("Ford", "Edge"); console.log(myCar.toString()); // > Dodge Charger console.log(wifeCar.toString()); // > Ford Edge

Slide 64

Slide 64 text

var Car = function(make, model) { this.make = make; this.model = model; this.toString = function() { return this.make + " " + this.model; }; }; var myCar = new Car("Dodge", "Charger"); var wifeCar = new Car("Ford", "Edge"); myCar.toString = function() { return this.model + ", " + this.make; }; console.log(myCar.toString()); // > Charger, Dodge console.log(wifeCar.toString()); // > Ford Edge

Slide 65

Slide 65 text

var Car = function(make, model) { this.make = make; this.model = model; }; Car.prototype.toString = function() { return "Model:" + this.model + ", Make:" + this.make; }; var myCar = new Car("Dodge", "Charger"); var wifeCar = new Car("Ford", "Edge"); console.log(myCar.toString()); // > Model:Charger, Make:Dodge console.log(wifeCar.toString()); // > Model:Edge, Make:Ford Car.prototype.toString = function() { return "Model:335i Convertible, Make:BMW"; } console.log(myCar.toString()); // > Model:335i Convertible, Make:BMW console.log(wifeCar.toString()); // > Model:335i Convertible, Make:BMW

Slide 66

Slide 66 text

prototype chain

Slide 67

Slide 67 text

var myPrototype = { sayFoo: function() { console.log("foo"); } }; obj = Object.create(myPrototype); obj.sayFoo(); // > foo

Slide 68

Slide 68 text

grandParent = { sayFoo: function() { console.log("foo"); } }; myPrototype = Object.create(grandParent); obj = Object.create(myPrototype); obj.sayFoo(); // > foo

Slide 69

Slide 69 text

grandParent = { sayFoo: function() { console.log("foo"); } }; myPrototype = Object.create(grandParent); myPrototype.bar = "I am set in myPrototype."; obj = Object.create(myPrototype); obj.sayFoo(); // > foo console.log(obj.bar); // > I am set in myPrototype.

Slide 70

Slide 70 text

grandParent = { sayFoo: function() { console.log("foo"); } }; myPrototype = Object.create(grandParent); myPrototype.bar = "I am set in myPrototype."; obj = Object.create(myPrototype); obj.sayFoo(); // > foo console.log(obj.bar); // > I am set in myPrototype. obj.bar = "I am overriding the myPrototype.bar property."; console.log(obj.bar); // > I am overriding the myPrototype.bar property.

Slide 71

Slide 71 text

grandParent = { sayFoo: function() { console.log("foo"); } }; myPrototype = Object.create(grandParent); myPrototype.bar = "I am set in myPrototype."; obj = Object.create(myPrototype); obj.sayFoo(); // > foo console.log(obj.bar); // > I am set in myPrototype. obj.bar = "I am overriding the myPrototype.bar property."; console.log(obj.bar); // > I am overriding the myPrototype.bar property. console.log(myPrototype.bar); // > I am set in myPrototype.

Slide 72

Slide 72 text

Resources 4.

Slide 73

Slide 73 text

JavaScript Essential Reading List http://crth.net/jsreading WatchMeCode.net JavaScript Fundamentals http://crth.net/jsfundamentals

Slide 74

Slide 74 text

Thanks. http://speakerdeck.com/jcarouth Q&A http://joind.in/8210