2

This is my source code but I have problem. I can't implementation showAll() function for Dictionary Data Structure.

Can you help me ?

function Dictionary() {
   this.add = add;
   this.datastore = new Array();
   this.find = find;
   this.remove = remove;
   this.showAll = showAll;
   this.count = count;
   this.clear = clear;
}
function add(key, value) {
   this.datastore[key] = value;
}
function find(key) {
   return this.datastore[key];
}
function remove(key) {
   delete this.datastore[key];
}
function showAll() {
    Object.keys(this.datastore).forEach( function(key, index) {
       console.log(key + "->" + this.datastore[key]);
    });
}
function count() {
    return Object.keys(this.datastore).length;
}
/*function count() {
   // var n = 0;
   // Object.keys(this.datastore).forEach( function(key, index) {
   // for each (var key in Object.keys(this.datastore)) {
   //      ++n;
   //};
   //return n;
}*/
function clear() {
   Object.keys(this.datastore).forEach( function(key, index) {
    // for each (var key in Object.keys(this.datastore)) {
      delete this.datastore[key];
  });
}

var pbook = new Dictionary();

pbook.add("Michael", "012345");
pbook.add("Sam", "54654654");
pbook.add("Shen", "5465464");

console.log("Sam's extension: " + pbook.find("Sam"));
pbook.remove("Sam");
pbook.showAll();

I get this error:

undefined:31
       console.log(key + "->" + this.datastore[key]);
                                              ^
TypeError: Cannot read property 'Michael' of undefined
    at eval (eval at <anonymous> (C:\DATA\NetBeansProjects\StudyForDTwithJS\public_html\js\CH07-Dictionaries\02-TestDictionaryDefinitionClass.js:8:56), <anonymous>:31:47)
    at Array.forEach (native)
    at Dictionary.showAll (eval at <anonymous> (C:\DATA\NetBeansProjects\StudyForDTwithJS\public_html\js\CH07-Dictionaries\02-TestDictionaryDefinitionClass.js:8:56), <anonymous>:30:33)
    at Object.<anonymous> (C:\DATA\NetBeansProjects\StudyForDTwithJS\public_html\js\CH07-Dictionaries\02-TestDictionaryDefinitionClass.js:18:7)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:501:10)
    at startup (node.js:129:16)
3

2 Answers 2

3

this inside the forEach callback is not the same this before calling because the execution context(fancy for a function has been invoked and a new scope created) has been changed. Preserve it in a variable and use it within the callback.

function showAll() {
    var ds = this.datastore;
    Object.keys(this.datastore).forEach( function(key, index) {
       console.log(key + "->" + ds[key]);
    });
}

function Dictionary() {
  this.add = add;
  this.datastore = new Array();
  this.find = find;
  this.remove = remove;
  this.showAll = showAll;
  this.count = count;
  this.clear = clear;
}

function add(key, value) {
  this.datastore[key] = value;
}

function find(key) {
  return this.datastore[key];
}

function remove(key) {
  delete this.datastore[key];
}

function showAll() {
  var ds = this.datastore;
  Object.keys(this.datastore).forEach(function(key, index) {
    console.log(key + "->" + ds[key]);
  });
}

function count() {
  return Object.keys(this.datastore).length;
}

/*
function count() {
   // var n = 0;
   // Object.keys(this.datastore).forEach( function(key, index) {
   // for each (var key in Object.keys(this.datastore)) {
   //      ++n;
   //};
   //return n;
}
*/
function clear() {
  Object.keys(this.datastore).forEach(function(key, index) {
    // for each (var key in Object.keys(this.datastore)) {
    delete this.datastore[key];
  });
}

var pbook = new Dictionary();

pbook.add("Michael", "012345");
pbook.add("Sam", "54654654");
pbook.add("Shen", "5465464");

console.log("Sam's extension: " + pbook.find("Sam"));
pbook.remove("Sam");
pbook.showAll();

Or, another option is to pass this into forEach as the documentation states

arr.forEach(callback[, thisArg])

function showAll() {
  var ds = this.datastore;
  Object.keys(this.datastore).forEach(function(key, index) {
    console.log(key + "->" + this[key]);
  }, this);
}

function Dictionary() {
  this.add = add;
  this.datastore = new Array();
  this.find = find;
  this.remove = remove;
  this.showAll = showAll;
  this.count = count;
  this.clear = clear;
}

function add(key, value) {
  this.datastore[key] = value;
}

function find(key) {
  return this.datastore[key];
}

function remove(key) {
  delete this.datastore[key];
}


function showAll() {
  var ds = this.datastore;
  Object.keys(this.datastore).forEach(function(key, index) {
    console.log(key + "->" + this[key]);
  }, this);
}

function count() {
  return Object.keys(this.datastore).length;
}

/*
function count() {
   // var n = 0;
   // Object.keys(this.datastore).forEach( function(key, index) {
   // for each (var key in Object.keys(this.datastore)) {
   //      ++n;
   //};
   //return n;
}
*/
function clear() {
  Object.keys(this.datastore).forEach(function(key, index) {
    // for each (var key in Object.keys(this.datastore)) {
    delete this.datastore[key];
  });
}

var pbook = new Dictionary();

pbook.add("Michael", "012345");
pbook.add("Sam", "54654654");
pbook.add("Shen", "5465464");

console.log("Sam's extension: " + pbook.find("Sam"));
pbook.remove("Sam");
pbook.showAll();

For further reading, see What is “this” Context

Sign up to request clarification or add additional context in comments.

3 Comments

This works, alternatively the forEach method takes an optional second argument to assign context: .forEach(callback,thisArg)
@Adam, I did not know that! Thanks for mentioning! I have included it in the answer!
@James, if you find an answer solved your problem, mark it as accepted by clicking the checkmark next to the answer.
0

I'd simply use a JavaScript object to store key/value pairs.

You can simply :

  • add property
  • delete property (remove)
  • read property (find)
  • show all properties (use for each key in object and hasOwnProperty to skip prototype chain)
  • count
  • clear (all properties)

Just a suggestion. Maybe it's more efficient I think.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.