In the example above getInfo() used this internally to address the object. Using Gadget.prototype we could achieve the same result:
Gadget.prototype.getInfo = function() { return 'Rating: ' + Gadget.prototype.rating + ', price: ' + Gadget.prototype.price; };
How the prototype works?
In newtoy object, when you try to access a property(newtoy.name) of newtoy the JavaScript engine will look through all of the properties of the object and, if it finds it, will return its value.
var newtoy = new Gadget('webcam', 'black'); newtoy.name "webcam"
In newtoy object, when you try to access the rating property the JavaScript engine will examine all of the properties of newtoy and will not find the one called rating. Then the script engine will identify the prototype of the constructor function used to create this object (same as if you do newtoy.constructor.prototype). If the property is found in the prototype, this property is used.
newtoy.rating 3
It would be the same as if we access the prototype directly. Every object has a constructor property, which is a reference to the function that created the object.
newtoy.constructor Gadget(name, color) newtoy.constructor.prototype.rating 3
Every object has a constructor. The prototype is an object, so it must have a constructor too, which in turn has a prototype.
newtoy.constructor.prototype.constructor Gadget(name, color) newtoy.constructor.prototype.constructor.prototype Object price=100 rating=3
This might go on for a while, depending on how long the prototype chain is, but eventually end up with the built-in Object() object, which is the highest-level parent. When you use newtoy.toString(), the newtoy and its prototype doesn't have an own toString(),so we get the Object's toString().
newtoy.toString() "[object Object]"
Enumerating Properties ......................
If you want to list all properties of an object, you can use a for-in loop. In Chapter 2, you saw how you could loop through all the elements of an array:
var a = [1, 2, 3]; for (var i in a) { console.log(a[i]); }
Arrays are objects, so you can expect that the for-in loop works for objects too:
var o = { p1: 1, p2: 2 }; for (var i in o) { console.log(i + '=' + o[i]); }
This produces:
p1=1 p2=2
There are some details to be aware of:
Not all properties show up in a for-in loop. For example, the length (for arrays) and constructor properties will not show up. The properties that do show up are called enumerable. You can check which ones are enumerable with the help of the propertyIsEnumerable() method that every object provides.
Prototypes that come through the prototype chain will also show up, provided they are enumerable. You can check if a property is an own property versus prototype's using the
Let's see these methods in action. Take this simplified version of Gadget():
function Gadget(name, color) { this.name = name; this.color = color; this.someMethod = function() { return 1; } } Gadget.prototype.price = 100; Gadget.prototype.rating = 3; & bull; & bull; & bull; < /p> < p >
var newtoy = new Gadget('webcam', 'black');
Now if you loop using a for-in, you see of the object's all properties, including those that come from the prototype:
for (var prop in newtoy) { console.log(prop + ' = ' + newtoy[prop]); }
The result also contains the object's methods (as methods are just properties that happen to be functions):
name = webcam color = black someMethod = function() { return 1; } price = 100 rating = 3
If you want to distinguish between the object's own properties versus the prototype's properties, use hasOwnProperty(). Try first:
newtoy.hasOwnProperty('name') true newtoy.hasOwnProperty('price') false
Let's loop again, but showing only own properties:
for (var prop in newtoy) { if (newtoy.hasOwnProperty(prop)) { console.log(prop + '=' + newtoy[prop]); } }
The result:
name=webcam color=black someMethod=function () { return 1; }
Now let's try propertyIsEnumerable(). This method returns true for own properties that are not built-in:
newtoy.propertyIsEnumerable('name') true
Most built-in properties and methods are not enumerable:
newtoy.propertyIsEnumerable('constructor') false
Any properties coming down the prototype chain are not enumerable:
newtoy.propertyIsEnumerable('price') false
Note, however, that such properties are enumerable if you reach the object contained in the prototype and invoke its propertyIsEnumerable().
newtoy.constructor.prototype.propertyIsEnumerable('price') true