Reputation: 237
I'm currently learning JS and ES6 in particular. I'm having trouble understanding why my code with class constructor and arrow functions doesn't work without a few changes.
Here is where I started, an ES6 module exporting this flux-like dispatcher object.
// RiotControl dispatcher formatted as ES6 module.
// https://github.com/jimsparkman/RiotControl
var dispatcher = {
stores: [],
addStore: function(store) {
this.stores.push(store);
}
};
['on','one','off','trigger'].forEach(function(api){
dispatcher[api] = function() {
var args = [].slice.call(arguments);
this.stores.forEach(function(el){
el[api].apply(null, args);
});
};
});
export default dispatcher
I wanted to make a class out of this code and originally ended up with:
// RiotControl dispatcher formatted as ES6 class module.
// https://github.com/jimsparkman/RiotControl
export default class {
constructor() {
this.stores = []
this.addStore = store => {
this.stores.push(store);
}
['on','one','off','trigger'].forEach(fn => {
this[fn] = () => {
var args = [].slice.call(arguments)
this.stores.forEach(function(el){
el[fn].apply(null, args)
})
}
})
}
}
For reasons unknown to me, this doesn't work.
.forEach(...)
results in Uncaught TypeError: Cannot read property 'forEach' of undefined
, as if the array is not defined.var args = [].slice.call(arguments)
results in args being a zero length array instead of actually, umm, having the arguments.To get the code working, I changed it to this:
// RiotControl dispatcher formatted as ES6 class module.
// https://github.com/jimsparkman/RiotControl
export default class {
constructor() {
this.stores = []
this.addStore = store => {
this.stores.push(store);
}
var api = ['on','one','off','trigger']
api.forEach(fn => {
this[fn] = function() {
var args = [].slice.call(arguments)
this.stores.forEach(function(el){
el[fn].apply(null, args)
})
}
})
}
}
Thus, the errors were fixed by
.forEach
on that andPlease explain why the forEach
with an inline array fails and why slicing the arguments list fails from inside the arrow function.
Also, bonus question, why is this
in ´this.stores.foreach` bound to my object instance and not e.g. the event that causes the function to be called?
Upvotes: 2
Views: 822
Reputation: 816364
Please explain why the
forEach
with an inline array fails and why slicing the arguments list fails from inside the arrow function.
The code is interpreted as follows:
this.addStore = store => { ... }['on','one','off','trigger'].forEach(...)
// which becomes
this.addStore = store => { ... }['trigger'].forEach(...)
I.e. you are trying to access the trigger
property of a function, which of course does not exist. Use a semicolon after the function definition to explicitly terminate the assignment expression:
this.addStore = store => {
this.stores.push(store);
};
['on','one','off','trigger'].forEach(...);
Also, bonus question, why is this in
this.stores.foreach
bound to my object instance and not e.g. the event that causes the function to be called?
this
is not bound here. What this
refers to depends on how the function is called, which you shouldn't show.
var args = [].slice.call(arguments)
results in args being a zero length array instead of actually, umm, having the arguments.
In arrow functions, both this
and arguments
are lexically scoped. I.e. arrow functions don't have their own arguments
object.
Upvotes: 1