Taking
JavaScript
Out Of
Context
$('.clickme').on('click', function() {
this.innerHTML = 'Wait 1 sec...';
setTimeout(function() {
this.innerHTML = 'Done!';
}, 1000);
// But it doesn't work?
});
var sayHi = person.sayHi;
sayHi();
'Hi, my name is undefined'
el.addEventListener('click', person.sayHi);
el.click();
'Hi, my name is undefined'
Every function shadows the value of this
When the function is called,
Look to the left of the dot.
person.sayHi();
// 'this' is person
sayHi();
// no dot, so 'this' is window
// (or undefined in strict mode)
new Person();
// 'this' is the new instance object
Question:
How do we define constructors?
var Person = function(name) {
this.name = name;
};
Question:
How do we define methods?
Once again...
With functions.
var person = {
name: 'Mark',
sayHi: function() {
return "Hi, I'm " + this.name;
}
};
If everything is a function...
var sayHi = function(){
return "Hi, I'm " + this.name;
};
var person = {
sayHi: sayHi
};
// function:
sayHi();
// constructor:
new sayHi();
// method:
person.sayHi();
Same function
called in three different ways
“Current functions playing triple duty is difficult to understand.”
Constructor, method, or
plain old function?
Passing a callback to someone else?
You're not the calling code
var runAsCallback = function(fn) {
fn();
// No dot,
// so 'this' is window
};
// Even if you pass it a method
runAsCallback(person.sayHi);
Can we explicitly set this?
// When calling a function
sayHi.call(person, arg1, arg2);
// or...
sayHi.apply(person, [arg1, arg2]);
// When passing a method as a callback
runAsCallback(
person.sayHi.bind(person)
);
// When trying to maintain the context
setTimeout(function() {
// etc...
}.bind(this), 1000);
Another option...
Only use functions,
as functions
function makePerson(name) {
var sayHi = function() {
return "Hi, I'm " + name;
};
return {
sayHi: sayHi
};
};
bespoke.from = function(el, plugins) {
var listeners = [],
on = function(e, fn) { },
next = function() { },
prev = function() { }, // etc...
return {
on: on,
next: next,
prev: prev, // etc...
};
};
Need private state? Simple.
Don't expose it.
No methods or constructors
Functions return objects,
powered by closures
“This is everything you need to make objects, and it all works because of functions”
Functions:
The Good Parts
ES6 makes this pattern easy
let makePerson = (name) => {
let sayHi = () => `Hi, I'm ${ name }`;
return { sayHi };
};
$('.clickme').on('click', function() {
this.innerHTML = 'Wait 1 sec...';
setTimeout(() => {
this.innerHTML = 'Done!';
}, 1000);
});
You don't need this, but you need to understand it
And if you only remember one thing...
Look to the left of the dot.
Thank you!
@markdalgleish