Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JavaScript's Difficult Concepts Explained

JavaScript's Difficult Concepts Explained

When approaching JavaScript as a PHP developer some of the nuances of the language take a while to become comfortable. If you've ever wondered how context and the this keyword work, when to declare a variable, how to create objects and use prototypes in JavaScript, you are not alone. These concepts seems crazy at first, but with some examples you can grasp and use them in your code today. This session will cover the finer points of JavaScript the language from the perspective of someone who is proficient with PHP or another language. - See more at: http://midwestphp.org/sessions/JavaScript's_Difficult_Concepts_Explained#sthash.nKUpmxaT.dpuf

Jeff Carouth

March 02, 2013
Tweet

More Decks by Jeff Carouth

Other Decks in Programming

Transcript

  1. reducing the wat-factor when PHPers write JS JavaScript’s Difficult Concepts

    Explained Jeff Carouth // @jcarouth // #midwestphp
  2. foo = "I am a globally-scoped var."; function sayFoo() {

    console.log(foo); } sayFoo(); // > I am a globally-scoped var.
  3. 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()
  4. 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
  5. 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.
  6. 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.
  7. foo = "I am global foo."; function myModule() { function

    sayFoo() { console.log(foo); } sayFoo(); } myModule(); // > I am a global foo.
  8. 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.
  9. 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
  10. (function() { var foo; function defineFoo() { foo = "I

    am a local variable."; } defineFoo(); console.log(foo); })(); // > I am a local variable.
  11. 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.
  12. 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
  13. var myModule = (function($, _) { return { display: function(a)

    { _.each(a, console.log); } } })(jQuery, _);
  14. <?php class Example { private $counter; private $closed; public function

    doSomethingMagic() { $this->counter = 5; $this->doSomethingElse(); } public function doSomethingElse() { // do something } }
  15. 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
  16. 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
  17. function myFoo() { var bar = "baz"; function something() {

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

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

    { console.log(bar); } this.something(); } myFoo(); // > baz something(); // > baz
  20. 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
  21. contextMethod = { logContext: function() { console.log(this); } }; contextMethod.logContext();

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

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

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

    foo.logContext(); // > Object { logContext: [Function] } foo.logContext.call(); // > Global foo.logContext.call(this); // > Global
  25. 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" }
  26. 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
  27. 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
  28. {}

  29. var foo = { bar: "baz", fizz: "buzz", bang: function()

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

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

    new someFunction(); console.log(obj); // > Object [someFunction] // > Object [someFunction]
  32. 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]
  33. 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: ...
  34. 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
  35. 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
  36. 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
  37. var myPrototype = { sayFoo: function() { console.log("foo"); } };

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

    = Object.create(grandParent); obj = Object.create(myPrototype); obj.sayFoo(); // > foo
  39. 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.
  40. 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.
  41. 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.