The complete elimination and eradication of JavaScript's this.
If this is so difficult to reason about, why don't we just stop using it? Seriously. Why. don't. we. just. stop. using. it.?
When a function is decorated with the nothis
function decorator it will pass this
as the first argument. Read more on function decorators here.
Now you can remove all those annoying var self = this
lines as they are now completely unnecessary!
npm install nothis
nothis
- passesthis
as an argument.fixthis
- Prevents the rebinding ofthis
.nothisAll
- Prevents the rebinding ofthis
for React.
Basic JavaScript object
// 😞 GROSS: this
const cat = {
sound: 'meow',
speak: function() {
return this.sound
}
}
// 🔥 LIT: nothis
import nothis from 'nothis'
const cat = {
sound: 'meow',
speak: nothis(function(ctx) {
return ctx.sound
})
}
Arrow functions with this
won't work. But with nothis
you can still access the context.
// 😞 GROSS: this
const cat = {
sound: 'meow',
speak: () => this.sound
}
cat.speak()
//=> undefined
// 🔥 LIT: nothis
const cat = {
sound: 'meow',
speak: nothis(ctx => ctx.sound)
}
cat.speak()
//=> "meow"
const cat = {
sound: 'meow',
speak: nothis((ctx, end) => ctx.sound + end)
}
cat.speak('!')
// => "meow!"
Easily know what your context is.
// 😞 GROSS: this
const cat = {
sound: 'meow',
speak: function() {
return this.sound
},
crazy: function() {
setInterval(function() {
console.log(this.speak())
}, 1000)
}
}
cat.speak()
//=> Error: this.speak is not a function
// 🔥 LIT: nothis
const cat = {
sound: 'meow',
speak: function() {
return this.sound
},
crazy: nothis(function(ctx) {
setInterval(function() {
console.log(ctx.speak())
}, 1000)
})
}
cat.crazy()
// => "meow"
// => "meow"
// => "meow"
3rd party libraries sometimes require you to use this
. F that.
// 😞 GROSS: this
$('p').on('click', function() {
console.log($(this).text())
})
// 🔥 LIT: nothis
$('p').on('click', nothis(ctx => console.log($(ctx).text())))
You can also use parameter destructuring in ES6 arrow functions.
import { EventEmitter2 } from 'eventemitter2'
const events = new EventEmitter2({ wildcard: true })
// 😞 GROSS: this
events.on('button.*', function() {
console.log('event:', this.event)
})
// 🔥 LIT: nothis + destructuring!
events.on('button.*', nothis(({ event }) => console.log('event', event)))
events.emit('button.click')
Sometimes this
will get rebound to another context when you least expect it. Consider this example.
// 😞 GROSS: this
const cat = {
sound: 'meow',
speak: function() {
return this.sound
}
}
const speak = cat.speak
speak()
// => undefined
You can prevent this from happening by using fixthis
.
// 🔥 LIT: fixthis
import fixthis from 'nothis/fixthis'
const cat = fixthis({
sound: 'meow',
speak: function() {
return this.sound
}
})
const speak = cat.speak
speak()
// => "meow"
Classes won't save you from the problems of this
.
// 😞 GROSS: this
class Cat {
constructor() {
this.sound = 'meow'
}
speak() {
return this.sound
}
}
const cat = new Cat()
const speak = cat.speak
speak()
// => Cannot read property 'sound' of undefined
You still can fixthis
it.
// 🔥 LIT: fixthis
class Cat {
constructor() {
this.sound = 'meow'
}
speak() {
return this.sound
}
}
const cat = fixthis(new Cat())
const speak = cat.speak
speak()
//=> "meow"
Apply fixthisReact
to your React component and never have to use this
again!
import React from 'react'
import nothisAll from 'nothis/nothisAll'
// 🔥 LIT: no this in sight!
class Counter extends React.Component {
state = { count: 0 }
constructor() {
super()
nothisAll(this)
}
increment({ setState }) {
setState(({ count }) => ({ count: count + 1 }))
}
render({ increment, state }) {
return (
<div>
<button onClick={increment}>{state.count}</button>
</div>
)
}
}