Checking a prototype of an Object

let ages = {
  Boris: 39,
  Liang: 22,
  Julia: 62

console.log(toString in ages); // output: false
console.log("toString" in ages); // output: true

The goal with the code is to check whether toString function exists in the age object. The two output statements give out different results. What’s going on in line 7 and 8, when I think I mean the same thing?

console.log(toString in ages); // output: false

Here toString is an undeclared variable.

console.log("toString" in ages); // output: true

Here "toString" is a string.

So, the search for toString stops at the object’s scope whereas when given in double-quotes it searches for its prototype and so on?

In the first case, toString is undefined.

console.log(toString in ages);
// is functionally equivalent to
console.log(elephant in ages);
// or 
console.log(undefined in ages);

Yes. My doubt is when we’re essentially searching for an object’s property, why put it in quotes? What difference does that make?

You need to put it in quotes because the operator in expects a string.

toString === "toString" // false

Consider this example:

let ages = {
  Boris: 39,
  Liang: 22,
  Julia: 62

const toString = 'Boris';

console.log(toString in ages); // output: true because 'Boris' is in ages
console.log('toString' in ages); // output: true because toString is in ages --> prototype

I hope this will clarify a bit :slight_smile:

… also your solution will not complete the check as true on output doesn’t mean toString is a function

1 Like

I see. So, what happens when we type it without quotes, does it still check for toString property in the object?

console.log(Boris in ages); // output: Error because Boris is not defined and `in` expects a string. 
console.log(toString in ages); output: false

in expects a string, but why does the second statement in the code above does not throw an error like the first one because toString is also not defined?

I was a little off in my original response. If you just use toString on its own, it is a reserved word that JavaScript knows is a function. I can’t spend the time right now to dig into the implementation of in so I’m not sure how it tries to cast toString as a string. The main takeaway though, is that you need a string or something that resolves to a string for in to work.

@skanda1395, toString is then defined, because, as you said yourself, otherwise it would throw Reference Error.

In case you’re wondering how come it’s defined, whenever you accessing variable, JS engine searches it in all scopes starting from local and up to the global. If no luck, it does final lookup in the global context searching for the property of the same name. This last steps allows us to omit including name of the global object (window in browser and global in NodeJS) when accessing its properties, so we can do console.log() even though “full path” is actually window.console.log(). Now, knowing that global objects are JS objects, they have .toString() method in their prototype, so eventually whenever you write toString you actually accessing window.toString, which is a function.

toString === window.toString && toString === this.toString
// true

Whenever you write prop in object, JS takes value of prop and if it’s not a symbol, it turns it to a string and checks whether obj[prop] exists. So in your case:

window[toString] = 42;
toString in window; // true
console.log(window["function toString() { [native code] }"]); // 42