Use Prototype Properties to Reduce Duplicate Code: How to see all properties

Hello,

function Dog(name) {
  this.name = name;
  //this.numLegs = numLegs;

}
Dog.prototype.numLegs = 4;


// Only change code above this line
let beagle = new Dog("Snoopy");
console.log(beagle.numLegs)
console.log(beagle)

Result of console.log:
image

I wonder why console.log(beagle) return only { name: 'Snoopy' } ?
How to see all properties of “beagle” at once ?

Because numLegs is a property of the constructor, not of the instance itself.

console.log( "It haz a name: " + beagle.hasOwnProperty("name") );
console.log("It haz legs? " + beagle.hasOwnProperty("numLegs") );

From those, we can see that beagle has a name, but any legs are delegated to it from its constructor - it hasn’t any of its own.

I talked a bit more about the pros and cons of “inherited” or delegated object properties here: Clarification on Prototypes and not Repeating Oneself - #6 by snowmonkey

hello snowmonkey,
I had well understood the difference between the two. But I wondered if it was possible to see both at the same time. By only only one check.

Well, it is. Ish. Not entirely beautiful, but it is possible. You’d need to write a function to look at each ancestor in the prototype chain, make sure it’s a thing, and return that thing. So if I had something like this:

function Animal() { }

Animal.prototype = {
  kingdom: "Animalia",
  eat: function() {
    console.log("nom nom nom");
  }
};

function Dog(name) {
  this.name = name;
}

Dog.prototype = Object.create(Animal.prototype) ;
Dog.prototype.numLegs = 4;

const beagle = new Dog("Snoopy");

… at this point, beagle has a prototype chain that looks like beagle -> Dog -> Animal -> Object (because all objects, behind the scenes, are Objects). And each of those are providing an property. beagle has the name property, Dog has the numLegs, and Animal provides the kingdom property.

Ideally, if we want to see them all, we can’t from the beagle class. We need to write a function that would look at the current thing, see if it has a prototype and, if it does, call itself with that prototype. Easier to show than to explain:

const getPropertyTree = function(obj){
  // so do we *have* an object being passed in, and does it have a valid prototype?
  return obj && !!Object.getPrototypeOf(obj) 
       // if it does, return an array of all the other recursive calls, plus this object
       ? [...getPropertyTree(Object.getPrototypeOf(obj)), obj]
    
       // if it does *not* meet both those conditions, we've reached the end of the
       //  prototype chain - return an empty array.
       : []
}

console.log( getPropertyTree(beagle) );

// the above gives us this:
// [ 
//   { kingdom: 'Animalia', eat: [Function] },
//   { numLegs: 4 },
//   { name: 'Snoopy' } 
// ]

So we get an array containing a reference to each object in the prototype chain, letting us see what properties it might contain.

So stock, no. There is no way to see all the properties on a prototype chain. You can make something to show you those properties, as I have done, and it could be done differently, but the system has no in-built way, as far as I know (aside from using the Dev Tools in your browser of choice. :wink: ).

If you’d like to tinker with this live, see what you can do to change or improve it: https://replit.com/@TobiasParent/PrototypeTreeThing#script.js

1 Like

Hyy @snowmonkey, your code above is fantastic! :+1:

Can I ask you one thing? If yes then what do you mean by !! in your code? Is that a operator or something?

return obj && !!Object.getPrototypeOf(obj) ?

That is actually Boolean “double negation” - it isn’t entirely necessary here, but it’s a quick way of coercing a value to Boolean.

Object.getPrototypeOf either returns the prototype object, or null. Null evaluates to Boolean false, any other return value evaluates to Boolean true.

1 Like

Thank you snowmonkey :wink:

1 Like