Javascript - Prototypes and in Operator

Introduction

There are two ways to use the in operator:

  • on its own or
  • as a for-in loop.

When used on its own, the in operator returns true when a property is accessible by the object, on the instance or on the prototype.

Demo

function Person(){
}

Person.prototype.name = "First";
Person.prototype.age = 29;//from  w  w  w  . ja  v  a 2 s  .c  o m
Person.prototype.job = "writer";
Person.prototype.sayName = function(){
   console.log(this.name);
};

var person1 = new Person();
var person2 = new Person();

console.log(person1.hasOwnProperty("name"));  //false
console.log("name" in person1);  //true

person1.name = "Tom";
console.log(person1.name);   //"Tom" - from instance
console.log(person1.hasOwnProperty("name"));  //true
console.log("name" in person1);  //true

console.log(person2.name);   //"First" - from prototype
console.log(person2.hasOwnProperty("name"));  //false
console.log("name" in person2);  //true

delete person1.name;
console.log(person1.name);   //"First" - from the prototype
console.log(person1.hasOwnProperty("name"));  //false
console.log("name" in person1);  //true

Result

The property name is available on each object either directly or from the prototype.

Therefore, calling "name" in person1 always returns true, regardless of whether the property exists on the instance.

To determine if the property of an object exists on the prototype, combine a call to hasOwnProperty() with the in operator:

function hasPrototypeProperty(object, name){
   return !object.hasOwnProperty(name) && (name in object);
}

function Person(){
}

Person.prototype.name = "First";
Person.prototype.age = 29;
Person.prototype.job = "writer";
Person.prototype.sayName = function(){
   console.log(this.name);
};

var person = new Person();
console.log(hasPrototypeProperty(person, "name"));  //true

person.name = "Tom";
console.log(hasPrototypeProperty(person, "name"));  //false

When using a for-in loop, all properties that are accessible by the object and can be enumerated will be returned, which includes properties both on the instance and on the prototype.

Instance properties that shadow a non-enumerable prototype property (a property that has [[Enumerable]] set to false) will be returned in the for-in loop, since all developer-defined properties are enumerable by rule.

To retrieve a list of all enumerable instance properties on an object, use Object.keys() method.

It accepts an object as its argument and returns an array of strings containing the names of all enumerable properties.

Demo

function Person(){
}

Person.prototype.name = "First";
Person.prototype.age = 29;/*from   w  w  w  . j av  a 2 s.  c  o m*/
Person.prototype.job = "writer";
Person.prototype.sayName = function(){
   console.log(this.name);
};

var keys = Object.keys(Person.prototype);
console.log(keys);       //"name,age,job,sayName"

var p1 = new Person();
p1.name = "Rob";
p1.age = 31;
var p1keys = Object.keys(p1);
console.log(p1keys);    //"name,age"

Result

To list all instance properties, whether enumerable or not, use Object .getOwnPropertyNames():

var keys = Object.getOwnPropertyNames(Person.prototype);
console.log(keys);   //"constructor,name,age,job,sayName"

Related Topic