Skip to content

Instantly share code, notes, and snippets.

@roryokane
Last active October 15, 2017 06:38
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save roryokane/10b7d9f45bdece159431 to your computer and use it in GitHub Desktop.
Save roryokane/10b7d9f45bdece159431 to your computer and use it in GitHub Desktop.
Summary of this, call, and bind in JavaScript
// exploring `this` in JavaScript, and `.call` and `.bind`
// our cast
anna = {name: "Anna"};
zach = {name: "Zach"};
// how `this` works
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
anna.getName = function() { return this.name; };
console.log( anna.getName() ); // "Anna"
// `this` refers to `anna` in this case. `anna.name` is "Anna".
zach.getName = anna.getName;
console.log( zach.getName() ); // "Zach"
// With the reassigned function, `this` refers to `zach`.
// `this` in a function is the parent at the time of calling,
// not the time of definition.
// What is `this` in a function with no parent object?
var freeGetName = anna.getName;
console.log( freeGetName() ); // ""
// For a function with no parent object, when run in a browser, `this` is `window`.
// `window.name` defaults to "".
console.log( this ); // window
// Strict mode ("use strict") tries to protect you from this:
(function() {
"use strict";
console.log( this ); // undefined
})();
// But you can’t really rely on it:
(function() {
"use strict";
console.log( freeGetName() ); // "" (`window.name`)
})();
// If a function with no parent is running in strict mode (`"use strict";`), `this` will STILL be `window`.
// You would expect it to be `undefined` instead, but both Chrome and Firefox have `this` be `window`.
// Maybe it’s something the designers of "use strict" overlooked when defining it,
// and now they can’t change it because of backwards compatibility.
// how `call` and `apply` work
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
// In all examples on this page, `apply` would do the exact same thing as `call`.
// The only difference between `call` and `apply` is how they take extra arguments to call the function with.
// The examples on this page don’t use that feature, so I just demonstrate with `call`.
// `call` calls the function with `this` being the first argument.
// (`call` can also take arguments to pass through, but that’s irrelevant to this example.)
console.log( freeGetName.call(zach) ); // "Zach"
// It works the same no matter what object the function is currently attached to.
console.log( anna.getName.call(zach) ); // "Zach"
// how `bind` works
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
// `bind` locks the value of `this` to the passed object.
// The returned function will always ignore any other suggestions to use a different value of `this`.
zach.annaBoundGetName = anna.getName.bind(anna);
console.log( zach.annaBoundGetName() ); // "Anna" – not "Zach" like with `zach.getName`
var freeAnnaBoundGetName = anna.getName.bind(anna);
console.log( freeAnnaBoundGetName() ); // still "Anna"
// Can you re-bind a bound function?
var reboundGetName = freeAnnaBoundGetName.bind(zach);
console.log( reboundGetName() ); // still "Anna"
// No.
// how `call` and `bind` interact
console.log( zach.annaBoundGetName.call(zach) ); // still "Anna"
console.log( freeAnnaBoundGetName.call(zach) ); // still "Anna"
// A function resulting from `bind` *always* overrides the value of `this`.
// None of assignment to an object, `call`, or `bind` can change `this` again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment