我想在 javascript 中实现哈希表,但它有一个例外

I want to implement the hashtable in javascript but it has an exception

function HashTable(){
    var size = 0;
    var entry = new Object();
    this.add = function(key,value){
        if(!containsKey(key)){
            size++;
        }
        entry[key] = value;
    }

    this.getValue = function(key){
        return containsKey(key)?entry[key]:null;
    }

    this.remove = function(key){
        if (containsKey(key) && delete entry[key]) {
            size--;
        }
    }

    this.containsKey = function(key){
        return (key in entry);
    }

    this.containsValue = function(value){
        for(var prop in entry){
            if(entry[prop] == value){
                return true;
            }
        }
        return false;
    }
    //get all values
        this.getValues = function(){
            var values = new Array();
            for(var prop in entry){
                values.push(entry[prop]);
            }
            return values;
        }
    //get all keys
        this.getKeys = function(){
            var keys = new Array();
            for(var prop in entry){
                values.push(prop);
            }
            return keys;
        }
    this.getSize = function(){
        return size;
    }

    this.clear = function(){
        size = 0;
        entry = new Object;//???????????????????
    }
}

var hashtest = new HashTable();
hashtest.add('name','LiMing');

我想在javascript中实现哈希表,但是当我测试它时,出现了这样的异常:

未捕获的 ReferenceError:containsKey 未定义 在 HashTable.add (:8:3) 在 :64:10

改用this.containsKey,因为containsKeyHashTable创建的对象中的一个'member'方法,你必须用this引用它。

function HashTable(){
    var size = 0;
    var entry = new Object();
    
    this.containsValue = function(value){
        for(var prop in entry){
            if(entry[prop] == value){
                return true;
            }
        }
        return false;
    }
    
    this.add = function(key,value){
        if(!this.containsKey(key)){
            size++;
        }
        entry[key] = value;
    }

this.getValue = function(key){
    return this.containsKey(key)?entry[key]:null;
}

this.remove = function(key){
    if (this.containsKey(key) && delete entry[key]) {
        size--;
    }
}

this.containsKey = function(key){
    return (key in entry);
}


//get all values
    this.getValues = function(){
        var values = new Array();
        for(var prop in entry){
            values.push(entry[prop]);
        }
        return values;
    }
//get all keys
    this.getKeys = function(){
        var keys = new Array();
        for(var prop in entry){
            values.push(prop);
        }
        return keys;
    }
this.getSize = function(){
    return size;
}

this.clear = function(){
    size = 0;
    entry = new Object;//???????????????????
}
}

var hashtest = new HashTable(); hashtest.add('name','LiMing');
console.log(hashtest.getValues())

有一种使用 ES6 组织代码的更好方法:

class HashTable {
  constructor() {
    this.size = 0;
    this.entry = new Object();
  }
  
  containsValue(value) {
    for(var prop in entry){
      if(this.entry[prop] == value){
        return true;
      }
    }
    return false;
  }
  
  add(key,value) {
    if(!this.containsKey(key)){
      this.size++;
    }
    this.entry[key] = value;
  }
  
  getValue(key) {
    return this.containsKey(key) ? this.entry[key] : null;
  }
  
  remove(key) {
    if (this.containsKey(key) && delete this.entry[key]) {
      size--;
    }
  }
  
  containsKey(key) {
    return (key in this.entry);
  }
  
  //get all values
  getValues() {
    var values = new Array();
    for(var prop in this.entry){
      values.push(this.entry[prop]);
    }
    return values;
  }
  
  //get all keys
  getKeys() {
    var keys = new Array();
    for(var prop in this.entry){
      values.push(prop);
    }
    return keys;
  }
  
  getSize() {
    return this.size;
  }
  
  clear() {
    this.size = 0;
    this.entry = new Object();//???????????????????
  }
  
}


var hashtest = new HashTable(); hashtest.add('name','LiMing');
console.log(hashtest.getValues())

您遇到的问题是 scope 的问题。 javascript 解释器不知道您指的是 HashTable class 中的 containsKey

在 class 范围内调用函数时,请务必使用“this”引用它们。所以 containsKey 应该被引用为 this.containsKey(key)。这样解释器就知道您指的是 class' 范围而不是本地范围。

您还应该对范围为 class 的变量执行此操作。所以当你写 size++ 时,你实际上应该写 this.size++entry 也一样。如果您不添加 "this",它将假定它是一个局部函数或在该函数本身内定义的变量。

因此您应该将 add() 函数重写为

this.add = function(key,value){
        if(!this.containsKey(key)){
            this.size++;
        }
        this.entry[key] = value;
    }

你为什么要手动跟踪尺寸?您可以简单地将 "entry" 定义为数组并使用 this.entry.size

考虑到 hashmap 的更具体情况,我建议您在对象中简单地创建两个数组,一个用于键,一个用于值,这将为您大大简化问题,因为这样您就可以简单地使用内置的 Javascript 数组函数。两个数组都有一个数字索引,但键和值始终具有相同的索引,因此您可以轻松地对它们进行数学运算。结果将是这样的:

function HashTable() {
  this.keys = new Array();
  this.values = new Array();

  this.add = function(key, value) {

    if (this.containsKey(key)) {
      var index = this.keys.indexOf(key);
      this.values[index] = value;
    } else {
      this.keys.push(key);
      this.values.push(value);
    }
  }

  this.containsKey = function(key) {
    return this.keys.includes(key);
  }

  this.containsValue = function(value) {
    return this.values.includes(value);
  }

  this.get = function(key) {
    var index = this.keys.indexOf(key);
    return this.values[index];
  }

  this.remove = function(key) {
    if (this.containsKey(key)) {
      var index = this.keys.indexOf(key);
      this.keys.splice(index, 1);
      this.values.splice(index, 1);
    }
  }

  this.size = function() {
    return this.keys.length;
  }

  this.clear = function() {
    this.keys = new Array();
    this.values = new Array();
  }
}

// Create hashtable
var hashTable = new HashTable();

// Add some test data
hashTable.add('name', 'LiMing');
hashTable.add('location', 'At home');
hashTable.add('eyes', 'blue');

// Updates the value, doesn't add it
hashTable.add('eyes', 'brown');
console.log(hashTable.get("eyes"));

// Get the size
console.log(hashTable.size());

// Check if a value or key is in the hashtable
console.log(hashTable.containsValue("test")); // False
console.log(hashTable.containsValue("LiMing")); // True
console.log(hashTable.containsKey("name")); // True
console.log(hashTable.containsKey("age")); // False

// Get all the keys and values
console.log(hashTable.keys);
console.log(hashTable.values);

// Remove an item
hashTable.remove('eyes');
console.log(hashTable.keys);
console.log(hashTable.values);

// Clear hashtable
hashTable.clear();
console.log(hashTable.keys);
console.log(hashTable.values);