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

ZendCon 2013 - JavaScript's Difficult Concepts

ZendCon 2013 - JavaScript's Difficult Concepts

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.

Jeff Carouth

October 09, 2013
Tweet

More Decks by Jeff Carouth

Other Decks in Programming

Transcript

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

    console.log(foo); } sayFoo(); // > I am a globally-scoped var.
  2. 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()
  3. 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
  4. 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.
  5. 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]); } }
  6. <?php class Example { private $counter; private $closed; public function

    doSomethingMagic() { $this->counter = 5; $this->doSomethingElse(); } public function doSomethingElse() { // do something } }
  7. 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
  8. 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
  9. The this keyword and the context of the function depend

    entirely on how the function was invoked. Takeaway #2
  10. The default context will be the global context for functions

    invoked by name or variable name within the global context. Takeaway #3
  11. contextMethod = { logContext: function() { console.log(this); } }; contextMethod.logContext();

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

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

    var bar = { baz: "fizz" }; foo.logContext(); // > Object { logContext: [Function] } foo.logContext.call(bar); // > Object { baz: "fizz" }
  14. Using .call() and .apply() gives you the control you might

    need over the context inside a function or method. Takeaway #4
  15. {}

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

    { console.log(this.bar + " " + this.fizz); } }; foo.bang(); // > baz buzz
  17. <?php class Person { public function __construct($name) { $this->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."; } }
  18. function Person(name) { this.name = name; } Person.prototype.sayHello = function()

    { return "Hello. My name is " + this.name + "."; } function Developer(name) { Person.call(this, name); }
  19. function Developer(name) { Person.call(this, name); } // inherit from Person

    Developer.prototype = Object.create(Person.prototype);
  20. 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;
  21. 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."; }
  22. 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.
  23. 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
  24. 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
  25. Tip For more information on OOP JS, visit the Mozilla

    Developer Zone article at http://crth.net/mdnoopjs
  26. 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.