How does for loop index ascend the prototype chain?

Say I have an object person like so

var person = {   firstname: 'Default',   lastname: 'Default',   getFullName: function() {     return this.firstname + ' ' + this.lastname;   } } 

I make a new object john and set its prototype to that of person

var john = {   firstname: 'John',   lastname: 'Doe' }  john.__proto__ = person; 

if I console.log john, I see a tree structure like so

How does for loop index ascend the prototype chain?

where we see getFullName embedded under __proto__. Now here comes the surprise

for (var prop in john) {   console.log(prop) } 


How does for loop index ascend the prototype chain?

Even though getFullName was one level deep, somehow, the loop was able to find it.

Now, compare that to

var obj = {a: 1, b: {c:2, d: 3 }} for (var prop in obj) {console.log(prop)} 

which behaves as I expect, which is that c and d were not automagically found by the loop

How does for loop index ascend the prototype chain?

So how is it that in the former case the loop traversed deeper in to the tree to dig up embedded properties while in the latter it did not?


The loop will iterate all the own enumerable properties, as well as the inherited enumerable properties. That is why you are seeing getFullName in the loop.

But in the second case, it lists only the properties of obj, which are actually a and b only (c and d are properties of object b).

This is corresponding section from the language specification, for and it uses the internal [[Enumerate]] slot.

The internal [[Enumerate]] slot will be used to enumerate the object passed to it which gives the enumerable properties of the object. Quoting that section,

Enumerating the properties of the target object includes enumerating properties of its prototype, and the prototype of the prototype, and so on, recursively;

Since the goes up the prototype chain recursively, we are able to see the objects defined in the prototype, in this case getFullName.

If you don't want the getFullName to show up during the iteration, then you can define it as non-enumerable, like this

var person = {
  firstname: 'Default',
  lastname: 'Default'

Object.defineProperty(person, 'getFullName', {
  value: function() {
    return this.firstname + ' ' + this.lastname;
  enumerable: false

Now when you print the keys, getFullName will not be shown, as it is not enumerable anymore.

Note: Using __proto__ should be avoided, as it is not part of the ECMAScript specifications. Instead, you should use Object.setPrototypeOf.

Category: javascript Time: 2016-01-16 Views: 0

Related post

iOS development

Android development

Python development

JAVA development

Development language

PHP development

Ruby development


Front-end development


development tools

Open Platform

Javascript development

.NET development

cloud computing


Copyright (C), All Rights Reserved.

processed in 0.246 (s). 12 q(s)