简体   繁体   中英

Is it acceptable to use variable != null instead of variable !== undefined && variable !== null?

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) });

The semantics of != are well-defined. If you compare to null , then:

  • if "cur" is undefined or null , then the result is false
  • if "cur" is anything else, then the result is 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.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM