In for..in loop, property is assigned to the variable as a string i.e inside the loop, typeof(i) will always return "string". MDN explanation on how for..in works.
When accessed with the dot notation, engine tries to read as o."name", which it correctly finds as undefined. Please note o.name and o."name" are 2 different things.
Accessing object's properties using
the dot notation - property must be a valid JavaScript identifier i.e. property will get evaluated to return the required value.
the bracket notation - property is always a string. The string does not have to be a valid identifier, it can have any value, e.g. "1foo", "!bar!", or even " " (a space).
PS
When accessing object properties with for..in, Please note if you want to consider properties attached to the object only, and not its prototypes. In such a case use getOwnPropertyNames() or perform a hasOwnProperty() check. MDN explanation