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

This binding

This binding

A quick introduction on the 4 different types on how we can bind THIS on Javascript functions. WIP

Hector Yeomans

October 10, 2014
Tweet

Other Decks in Programming

Transcript

  1. “This” binding • Call-site: Where the function is called, not

    where it’s declared. • Go locate where a function is called from, not always easy, some coding patterns obscure this. • Think always on the call-stack, THINK OF THE CALL- STACK. • Call-stack: Stack of functions that have been called. • Call-site we care about is IN the invocation BEFORE the currently executing function.
  2. Rules for binding THIS • Default binding • Implicit binding

    • Implicitly lost • Explicit Binding • Hard Binding • new Binding
  3. Default Binding function foo() { console.log( this.a ); } !

    var a = 2; foo(); • var a = 2 is synonymous of global object. • They ARE NOT copies, they ARE each other • Call-site == Default binding
  4. Default Binding Strict Mode • Strict mode modifies semantics of

    JS • Avoids silent errors • Avoid invalid syntax likely not be supported on upcoming ECMAScript function foo() { "use strict"; console.log( this.a ); } ! var a = 2; foo(); // TypeError: `this` is`undefined`
  5. Default binding Mixing strict mode function foo() { console.log( this.a

    ); } ! var a = 2; ! (function(){ "use strict"; foo(); })();
  6. Implicit Binding • Call-site has a context object • Example:

    • foo is declared then assigned to obj • foo is owned/contained by obj • this.a is a synonym of obj.a == implicit binding. function foo() { console.log( this.a ); } ! var obj = { a: 2, foo: foo }; ! obj.foo(); // 2
  7. Implicitly lost • Common frustration when THIS loses the binding.

    • It goes back to the default binding. • It references to the global object or to undefined depending on strict mode. • Call-site is what matters. • bar() undecorated call == default binding. function foo() { console.log( this.a ); } ! var obj = { a: 2, foo: foo }; ! var bar = obj.foo; var a = "oops, global"; ! bar();
  8. Implicitly lost function foo() { console.log( this.a ); } !

    function doFoo(fn) { fn(); // <-- call-site! } ! var obj = { a: 2, foo: foo }; ! var a = "oops, global"; doFoo( obj.foo ); function foo() { console.log( this.a ); } ! var obj = { a: 2, foo: foo }; ! var a = "oops, global"; setTimeout( obj.foo, 100 );
  9. Exercise • Complete .where(predicate) and .each(callback) • Implement .any(predicate): •

    This method shall return a true value if any of the elements in the array satisfies the given predicate. • If the spec is a function then it shall be called for each element in the array, whenever the spec function returns a true value then immediately the any function will success (return a true value), but if it doesn’t for any of the collection elements then the any function will fail (return false value). • If the spec parameter is not a function object, then it will be tested against each element of the array and it will success if any elements matches the spec parameter value.
  10. Exercise continued… You could rewrite the previous code to look

    something like this: people.where(function(dev){ return !dev.skills.any(function(skill) { return skill == 'PHP' }); }) .each(logPerson) Or you could do this: people.where(function(dev){ return !dev.skills.any('PHP'); }) .each(logPerson)
  11. Explicit Binding • Forcing functional call to bind THIS •

    ‘All’ functions have methods via their Prototype. We’ are
 interested in ‘CALL’ and ‘APPLY’ function foo() { console.log( this.a ); } ! var obj = { a: 2 }; ! foo.call( obj ); // 2 • If we pass a primitive
 as first param, it will be
 wrapped in its object
 form. Formerly known
 as ‘Boxing’
  12. Hard-Binding function foo() { console.log( this.a ); } ! var

    obj = { a: 2 }; ! var bar = function() { foo.call( obj ); }; ! bar(); // 2 setTimeout( bar, 100 ); // 2 ! // hard-bound `bar` can no longer // have its `this` overridden bar.call( window ); // 2 function foo() { console.log( this.a ); } ! var obj = { a: 2 }; ! foo.call(obj); setTimeout(foo.call(obj), 100); ! foo.call(window);
  13. Hard-Binding function foo(something) { console.log( this.a, something ); return this.a

    + something; } ! var obj = { a: 2 }; ! var bar = function() { return foo.apply( obj, arguments ); }; ! var b = bar( 3 ); // 2 3 console.log( b ); // 5