Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

Wat? 0.

Slide 4

Slide 4 text

var_dump([] + []);

Slide 5

Slide 5 text

var_dump([] + []); // => []

Slide 6

Slide 6 text

console.dir([] + []);

Slide 7

Slide 7 text

console.dir([] + []); // => ''

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

Scope 1.

Slide 10

Slide 10 text

global& function

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 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 14

Slide 14 text

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

Slide 15

Slide 15 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 16

Slide 16 text

Avoid using global variables inside function scope by declaring them with the var keyword. Takeaway #1

Slide 17

Slide 17 text

Tip Declare all variables at the top of your function. function myFunction(input) { var i, count; for (i = 0, count = input.length; i < count; i++) { console.log(input[i]); } }

Slide 18

Slide 18 text

Context 2.

Slide 19

Slide 19 text

this PLEASE EXPLAIN

Slide 20

Slide 20 text

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

Slide 21

Slide 21 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 22

Slide 22 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 23

Slide 23 text

The this keyword and the context of the function depend entirely on how the function was invoked. Takeaway #2

Slide 24

Slide 24 text

default context

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

The default context will be the global context for functions invoked by name or variable name within the global context. Takeaway #3

Slide 29

Slide 29 text

method context

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

.call() & .apply()

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

Using .call() and .apply() gives you the control you might need over the context inside a function or method. Takeaway #4

Slide 36

Slide 36 text

Objects & Prototypes 3.

Slide 37

Slide 37 text

{}

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

prototype chain JavaScript’s complicated inheritance model Object Oriented JavaScript and the

Slide 40

Slide 40 text

name = $name; } public function sayHello() { return "Hello. My name is {$this->name}."; } } class Developer extends Person { public function __construct($name) { parent::__construct($name); } public function sayHello() { return parent::sayHello() . " I am a developer."; } }

Slide 41

Slide 41 text

function Person(name) { this.name = name; } Person.prototype.sayHello = function() { return "Hello. My name is " + this.name + "."; }

Slide 42

Slide 42 text

Tip Use Function.prototype to add methods to your constructor functions for performance reasons.

Slide 43

Slide 43 text

function Person(name) { this.name = name; } Person.prototype.sayHello = function() { return "Hello. My name is " + this.name + "."; } function Developer(name) { Person.call(this, name); }

Slide 44

Slide 44 text

function Developer() { Person.call(this); } // inherit from Person Developer.prototype = Object.create(Person.prototype);

Slide 45

Slide 45 text

function Developer(name) { Person.call(this, name); } // inherit from Person Developer.prototype = Object.create(Person.prototype);

Slide 46

Slide 46 text

function Developer(name) { Person.call(this, name); } // inherit from Person Developer.prototype = Object.create(Person.prototype); // correct the prototype constructor from Person to Developer Developer.prototype.constructor = Developer;

Slide 47

Slide 47 text

function Developer(name) { Person.call(this, name); } // inherit from Person Developer.prototype = Object.create(Person.prototype); // correct the prototype constructor from Person to Developer Developer.prototype.constructor = Developer; // override the sayHello method of Person for Developers Developer.prototype.sayHello = function() { return Person.prototype.sayHello.call(this) + " I am a developer."; }

Slide 48

Slide 48 text

var p = new Person('PersonGuy'); var d = new Developer('DeveloperGal');

Slide 49

Slide 49 text

var p = new Person('PersonGuy'); var d = new Developer('DeveloperGal'); console.log(p.sayHello()); // > Hello. My name is PersonGuy. console.log(d.sayHello()); // > Hello. My name is DeveloperGal. I am a developer.

Slide 50

Slide 50 text

var p = new Person('PersonGuy'); var d = new Developer('DeveloperGal'); console.log(p.sayHello()); // > Hello. My name is PersonGuy. console.log(d.sayHello()); // > Hello. My name is DeveloperGal. I am a developer. console.log(p instanceof Person); // > true console.log(p instanceof Developer); // > false

Slide 51

Slide 51 text

var p = new Person('PersonGuy'); var d = new Developer('DeveloperGal'); console.log(p.sayHello()); // > Hello. My name is PersonGuy. console.log(d.sayHello()); // > Hello. My name is DeveloperGal. I am a developer. console.log(p instanceof Person); // > true console.log(p instanceof Developer); // > false console.log(d instanceof Developer); // > true console.log(d instanceof Person); // > true

Slide 52

Slide 52 text

Tip For more information on OOP JS, visit the Mozilla Developer Zone article at http://crth.net/mdnoopjs

Slide 53

Slide 53 text

Object oriented development in JavaScript requires an understanding of the prototype. Takeaway #5

Slide 54

Slide 54 text

Resources 4.

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

Recap 5. All Objects have a prototype through which we can accomplish inheritance in JS. 1. Avoid using global vars inside function scope. 2. Context and this depend on invocation. 3. Default context is the global context. 4. .call() and .apply() gives you control over the context.

Slide 57

Slide 57 text

JEFF CAROUTH DEVELOPER AT LIFTOPIA @jcarouth [email protected] Freenode: #phpmentoring

Slide 58

Slide 58 text

Thanks. http://speakerdeck.com/jcarouth Q&A http://joind.in/9339 Jeff Carouth // @jcarouth // #zendcon