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

0f930e13633535c1c4041e95b8881308?s=128

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. JEFF CAROUTH DEVELOPER AT LIFTOPIA @jcarouth

  3. None
  4. None
  5. Wat? 0.

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

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

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

    []); '' ''
  9. WAT? https://www.destroyallsoftware.com/talks/wat

  10. Scope 1.

  11. global& function

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

    I am a globally-scoped var.
  13. foo = "I am a globally-scoped var."; function sayFoo() {

    console.log(foo); } sayFoo(); // > I am a globally-scoped var.
  14. 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()
  15. 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
  16. 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.
  17. variable hoisting

  18. 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.
  19. “private variables”

  20. foo = "I am global foo."; function myModule() { function

    sayFoo() { console.log(foo); } sayFoo(); } myModule(); // > I am a global foo.
  21. 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.
  22. 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
  23. IIFE&Modules

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

  25. (function() { var foo; function defineFoo() { foo = "I

    am a local variable."; } defineFoo(); console.log(foo); })(); // > I am a local variable.
  26. 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.
  27. 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
  28. locally-scoped globals

  29. var myModule = (function($, _) { return { display: function(a)

    { _.each(a, console.log); } } })(jQuery, _);
  30. Context 2.

  31. this PLEASE EXPLAIN

  32. <?php class Example { private $counter; private $closed; public function

    doSomethingMagic() { $this->counter = 5; $this->doSomethingElse(); } public function doSomethingElse() { // do something } }
  33. 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
  34. 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
  35. global& function

  36. function myFoo() { var bar = "baz"; function something() {

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

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

    { console.log(bar); } this.something(); } myFoo(); // > baz something(); // > baz
  39. 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
  40. default context

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

  43. function contextMagic() { function logContext() { console.log(this); } logContext(); }

    contextMagic(); // > Global
  44. method context

  45. contextMethod = { logContext: function() { console.log(this); } }; contextMethod.logContext();

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

    // > Object { logContext: [Function] } var myContextLogger = contextMethod.logContext; myContextLogger(); // > Global
  47. .call() & .apply()

  48. var foo = { logContext: function() { console.log(this); } };

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

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

    foo.logContext(); // > Object { logContext: [Function] } foo.logContext.call(); // > Global foo.logContext.call(this); // > Global
  51. 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" }
  52. 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
  53. 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
  54. Objects & Prototypes 3.

  55. {}

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

    { console.log(this.bar + " " + this.fizz); } }; foo.bang(); // > baz buzz
  57. functions

  58. var logContext = function() { console.log(this); }; console.log(logContext); // >

    [Function] console.log(typeof logContext); // > function
  59. Classes PROTOTYPES

  60. var someFunction = function() { console.log(this); }; var obj =

    new someFunction(); console.log(obj); // > Object [someFunction] // > Object [someFunction]
  61. 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]
  62. 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: ...
  63. 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
  64. 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
  65. 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
  66. prototype chain

  67. var myPrototype = { sayFoo: function() { console.log("foo"); } };

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

    = Object.create(grandParent); obj = Object.create(myPrototype); obj.sayFoo(); // > foo
  69. 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.
  70. 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.
  71. 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.
  72. Resources 4.

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

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