Reputation: 1598
For some reason, I cannot get the length of an array (it is undefined if it's unpopulated, right?).
define(function() {
'use strict';
var self = {},
events = {};
self.publish = function publish(eventName, data) {
var subscribers, x, length;
if (events[eventName]) {
return false;
}
subscribers = events[eventName];
for (x = 0, length = subscribers.length || 0; x < length; x += 1) {
subscribers[x](data);
}
return true;
};
self.subscribe = function subscribe(eventName, func) {
if (!events[eventName]) {
events[eventName] = [];
}
events[eventName].push(func);
};
return self;
});
JSLint says: "Expected ';' and instead saw ','." Jasmine says "TypeError: Cannot read property 'length' of undefined"
Why isn't length set to 0? Have I misunderstood the syntax an operations here?
Upvotes: 0
Views: 81
Reputation: 1598
As it turns out, the code worked fine when I fixed the typo.
if (events[eventName]) {
is supposed to be
if (!events[eventName]) {
Everything worked as intended after that correction. My debugging issues are always something stupidly minor
Upvotes: 0
Reputation: 2669
like Don Bhrayan Singh said
your code should be
for (var x = 0, length = subscribers.length || 0; x < length; x += 1) {
subscribers[x](data);
}
your previous code will run like this
// x = 0, 0 ; x < undefined; x += 1
for (x = 0, subscribers.length || 0; x < length; x += 1) {
subscribers[x](data);
}
Upvotes: -1
Reputation: 29906
You are missing a negation in the publish
function:
self.publish = function publish(eventName, data) {
var subscribers, x, length;
if (events[eventName]) { // <= Here you exit if there are subscribers, and continue if there arent
return false;
}
subscribers = events[eventName]; // So subscribers is guaranteed to be undefined
// can't get length (or any property) of undefined
for (x = 0, length = subscribers.length || 0; x < length; x += 1) {
...
This causes your tests to fail. This is the way to go:
self.publish = function publish(eventName, data) {
// you can use const and let
// you are storing subscribers in a variable anyway, so why not doing it
// before the check?
const subscribers = events[eventName];
if (!subscribers) {
return false;
}
// you don't need to cache length in a variable, iirc it only improves performance slightly on IE browsers
// neither need you `|| 0`
// there other ways iterating through an array, see for..of and Array.prototype.forEach
for (let x = 0; x < subscribers.length; x++) {
subscribers[x](data);
}
return true;
};
it is undefined if it's unpopulated, right?
No, the length of an array is zero if its empty. You get an undefined when reading a missing property of an object, but the length of an array is always a number.
Upvotes: 3
Reputation: 475
I think the problem is with this line:
for (x = 0, subscribers.length || 0; x < length; x += 1) {
you defined the variable "length" but never initialized / assigned data to it.
In detail:
subscribers.length || 0
Whats this supposed to do?
x < length
x < length or x < subscribers.length?
Upvotes: 0