Reputation: 64919
I have some code that where a variable could be undefined
, null
, or a normal value. The code needs to do the same thing regardless of whether the variable is undefined
or null
. Is there a danger to saying
for (var cur = this.buckets[i]; cur != null; cur = cur.next) {
instead of
for (var cur = this.buckets[i]; cur !== undefined && cur !== null; cur = cur.next) {
The full program is below (the line in question is in HashTable.prototype.walk
).
var hash_seed = Math.floor(Math.random() * 256);
function jenkins_hash(key, interval_size) {
var hash = hash_seed;
for (var i=0; i<key.length; ++i) {
hash += key.charCodeAt(i);
hash += (hash << 10);
hash ^= (hash >> 6);
}
hash += (hash << 3);
hash ^= (hash >> 11);
hash += (hash << 15);
// make unsigned and modulo interval_size
return (hash >>> 0) % interval_size;
}
//constructor, takes the number of buckets to create
function HashTable(size) {
this.buckets = new Array(size);
}
//private method, ignore
HashTable.prototype._position = function(key) {
var index = jenkins_hash(key, this.buckets.length);
var cur = this.buckets[index];
if (cur === undefined) {
return { i: index, cur: null, prev: null };
}
var prev = cur;
for (; cur !== null; cur = cur.next) {
if (cur.key == key) {
return { i: index, cur: cur, prev: prev };
}
prev = cur;
}
return { i: index, cur: cur, prev: prev };
};
// associate a value with a key in the hash
HashTable.prototype.store = function(key, value) {
var r = this._position(key);
if (r.prev === null) {
this.buckets[r.i] = {
key: key, value: value, next: null
};
return;
}
if (r.cur !== null) {
r.cur.value = value;
return;
}
r.prev.next = {
key: key, value: value, next: null
};
return;
};
// fetches the value associated with the key
// returns undefined if the key is not in the hash
HashTable.prototype.fetch = function(key) {
var r = this._position(key);
if (r.cur === null) {
return undefined;
}
return r.cur.value;
};
// returns true if the key is in the hash
// returns false if the key isn't in the hash
HashTable.prototype.exists = function(key) {
var r = this._position(key);
return r.cur !== null;
};
// removes a key from the hash
HashTable.prototype.delete = function(key) {
var r = this._position(key);
if (r.cur === null) {
return;
}
if (r.cur === r.prev) {
this.buckets[r.i] = r.cur.next;
}
r.prev.next = r.cur.next;
};
// removes all keys from the hash
HashTable.prototype.clear = function() {
var length = this.buckets.length;
this.buckets = new Array(length);
};
// run a funciton for every key/value pair in the hash
// function signature should be function(k, v) {}
// WARNING: adding keys to the hash while this method is
// running may lead to unexpected results
HashTable.prototype.walk = function(func) {
for (var i = 0; i < this.buckets.length; i++) {
for (var cur = this.buckets[i]; cur != null; cur = cur.next) {
func(cur.key, cur.value);
}
}
};
// returns all of the keys in the hash
HashTable.prototype.keys = function() {
var keys = [];
this.walk(function(k,v) { keys.push(k) });
return keys;
};
// run a function for every key/value pair in the hash
// function signature should be function(k, v) {}
// WARNING: only keys in the hash when the method is called
// will be visited; however, changes to their values will be
// reflected
HashTable.prototype.safer_walk = function(func) {
var keys = this.keys();
for (var i = 0; i < keys.length; i++) {
func(keys[i], this.fetch(keys[i]));
}
}
var h = new HashTable(101);
h.store("abc", 5);
h.store("def", 6);
h.walk(function(k, v) { console.log(k + " => " + v) });
Upvotes: 4
Views: 134
Reputation: 413826
The semantics of !=
are well-defined. If you compare to null
, then:
undefined
or null
, then the result is false
true
The "abstract" equality comparison (like the strict comparison) first checks the type of each operand (which, note well, is different from what typeof
returns!). The type of null
is the Null type, and the type of undefined
is the Undefined type. The abstract comparison algorithm explicitly considers undefined
and null
to be equal.
Thus there's really no point doing your own explicit check for both null
and undefined
. (You may want to check separately of course if you need logic that's different from the abstract comparison built into the language.)
Upvotes: 5