Reputation: 729
Just made the switch over to ES6, running io.js.
I'm writing some class code, but I'm having an unexpected error.
'use strict';
var _ = require('lodash');
class Country {
constructor(blocked) {
this.blocked = ['USA'];
}
ok(input) {
console.log('Receiving...',input['country']);
console.log('Blocked:', this.blocked);
if(_.includes('USA', input['country'])) {
return -1;
}
return 0;
}
}
module.exports = Country;
For whatever reason, everything works well except for the this.blocked
class variable.
When I console log it, it shows up as Blocked: undefined
.
Any thoughts as to what's going on here?
Addition
I'm calling the function in another class as follows...
var Country = require('./filters/country.js');
var country = new Country();
class FilterClassifier {
constructor() {
var self = this;
self.filters = [country.ok];
}
userFilter(params) {
var self = this;
var input = {
country : params.country,
};
console.log(self.filters[0](input));
}
}
module.exports = FilterClassifier;
Upvotes: 2
Views: 1810
Reputation: 5605
It looks like this.blocked
is scoped to the constructor
function, this
in ok
doesn't have a identifier called blocked
.
Edit: I was wrong, thanks Pointy. In the interest of helping others who stumble on this post I'm not going to delete my wrong answer but instead share what I learned. David, in the comments you asked for a way to fix it. this
could be replaced with let variables to avoid confusion or use this
with bind()
when a function is called.
class Country {
// variable scoped to class with let
// set blocked = value in constructor
// should not need 'this.' nor 'bind()'
let blocked = [];
...
}
"Determining this
" says you had default this
binding: undefined. You hoped for implicit binding and got explicit binding to work with country.ok.bind(country)
.
Further reading illustrating how the fat arrow =>
and var self = this;
make this
confusing.
Upvotes: 0
Reputation: 161647
As mentioned in the comments, the way you are calling the function removed the context of the function.
self.filters = [country.ok];
and then
console.log(self.filters[0](input));
means that this
inside ok
will not be country
. You'll need to do
self.filters = [country.ok.bind(country)];
or
self.filters = [() => country.ok()];
I'd recommend reading up on this
in javascript. The short answer in this particular case is that this
is defined based on how a function is called.
var a = {};
a.fn = function(){};
var b = {};
b.fn = a.fn;
b.fn();
When calling b.fn()
, this
inside the function is b
. This is because when calling a function using the form foo.bar()
, this
inside a function is defined as the object that the function is called on (foo
). In your case, you have
self.filters[0]();
that means that this
inside your ok
functions is actually self.filters
for the same reason.
If you have a specific this
that matters, it is your responsibility to make sure that as you pass around a function, that the function you are passing will set the proper this
. Using fn.bind(foo)
will return a new function which, when called, call fn
with a given this
.
Upvotes: 4