Search code examples
javascriptdata-structuresgraphnulljavascript-objects

Error using console.log on an Object, created with no prototypes && Accessing arrays with Stringed properties worked.. how?


I am reading Eloquent JavaScript 3rd Edition (https://eloquentjavascript.net/), and in Chapter 7, Marjin Haverbeke created a graph data structure, using this function.

function buildGraph(edges) {
  let graph = Object.create(null);
  function addEdge(from, to) {
    if (graph[from] == null) {
      graph[from] = [to];
    } else {
      graph[from].push(to);
    }
  }

  for (let [from, to] of edges.map(r => r.split("-"))) {
    addEdge(from, to);
    addEdge(to, from);
  }
  return graph;
}
const roads = ["Alice's House-Bob's House", "Alice's House-Post Office", "Daria's House-Ernie's House", "Ernie's House-Grete's House", "Grete's House-Shop"];

const roadGraph = buildGraph(roads);

So then I tried console.log(roadGraph);

And it gave me this error:

TypeError: obj.toString is not a function. (In 'obj.toString()', 'obj.toString' is undefined)

And then when I replace

let graph = Object.create(null); (line 2 in buildGraph function)

With

let graph = {};

And console.log(roadGraph);

It returns a graph-like object of arrays of expected strings.

Meanwhile if I use let graph=[]; it returns an empty array, when I use console.log(roadGraph);

But if I console.log(roadGraph.property); it displays correctly the value of the property

Please I need a Javascript guru to explain why these things happen.

  • What is the main reason for creating an Object with no prototypes in this function.
  • Why can’t I look at all properties and values of the object created with no prototype at once.
  • It displays an empty array, when I try looking at the values, but then if I try accessing a value in the array, with a “Stringed property” it displays correctly the value of the Stringed Property. Does this means array names/properties can be strings?? (Because I was told arrays could only be accessed with indexes[numbers])

Solution

  • What is the main reason for creating an Object with no prototypes in this function.

    The object was created with no prototype so that it couldn't be affected by additions to a prototype and was a fresh start to define as the programmer saw fit. It's not really necessary, but it does make the object more separate from traditional ones.

    Why can’t I look at all properties and values of the object created with no prototype at once.

    This is simply because without a prototype, the object won't be able to access the Object.toString() method that other objects have access to through their prototype chain. If you were to create your own toString function, or take the existing one and put it on this object, then the object's properties would be able to be converted to a string just like any other object. Basically, this is a side effect or having no prototype. It also shows what that really means-- none of the traditional object methods work on this one without workarounds.

    It displays an empty array, when I try looking at the values, but then if I try accessing a value in the array, with a “Stringed property” it displays correctly the value of the Stringed Property. Does this means array names/properties can be strings?? (Because I was told arrays could only be accessed with indexes[numbers])

    Arrays are actually just a variation of a normal object. They can have string-indexed properties as well as number-indexed properties. However, this should not be done in most cases, unless you know what you're doing and are trying to eg. add a method to your array. (Array methods, like Array.splice(), are named properties; this is an example of why having named properties on arrays can be useful).