admin管理员组

文章数量:1220074

I would like to make some properties of an object to be hidden and some to be visible on iteration. So I tried to use prototype but that's not working:

​function Car(){}

Car.prototype.version = '1.0';

var car_instance = new Car();
car_instance.make = 'BMW';
car_instance.model = 'x5';

for(property in car_instance){
    document.body.innerHTML += property + '<br>';
}

But this outputs version too:

make
model
version

I really like the idea to hide some functions/methods but access it easily like car_instance.version, and in fact if I console.log the object it has other properties too under proto which are not included in the for in loop.

So how should I solve this?

I would like to make some properties of an object to be hidden and some to be visible on iteration. So I tried to use prototype but that's not working:

​function Car(){}

Car.prototype.version = '1.0';

var car_instance = new Car();
car_instance.make = 'BMW';
car_instance.model = 'x5';

for(property in car_instance){
    document.body.innerHTML += property + '<br>';
}

But this outputs version too:

make
model
version

I really like the idea to hide some functions/methods but access it easily like car_instance.version, and in fact if I console.log the object it has other properties too under proto which are not included in the for in loop.

So how should I solve this?

Share Improve this question edited Jan 17 at 5:55 DarkBee 15.6k8 gold badges70 silver badges115 bronze badges asked Jun 10, 2012 at 17:42 Adam HalaszAdam Halasz 58.3k67 gold badges153 silver badges216 bronze badges 1
  • Prototype makes it so that each new instance of the object has that property. It's especially useful for methods and memory conservation. – vol7ron Commented Jun 10, 2012 at 17:53
Add a comment  | 

5 Answers 5

Reset to default 7

If you want to "hide" a property from a for in loop which is a direct property of the instance, you could use Object.defineProperty:

Object.defineProperty(car_instance, "version", {
  value: "1.0",
  writable: true,
  configurable: true,
  enumerable: false  // don't make it appear in a for in loop
});

To create a private variable, you will have to declare it inside function since JS has functional scope:

function Car(){
  // private var
  var version = '1.0';
  // public var
  this.foo = 'something';
}

When iterating over an object, use hasOwnProperty to get the actual object properties only:

for(property in car_instance){
   if (car_instance.hasOwnProperty(property)) {
     document.body.innerHTML += property + '<br>';
   }
}

More Info:

http://javascript.crockford.com/private.html

for(property in car_instance){
    if (car_instance.hasOwnProperty(property)) {
        document.body.innerHTML += property + '<br>';
    }​
}

It outputs:

 make
 model


Or alternatively:

var car = Object.create(null);
​car.make = 'BMW';
car.model = 'x5';

for(property in car) {
    document.body.innerHTML += property + '<br>';
}

Skip Named Properties:

function Car(){
   this.private = {};
}

var inst = new Car();
inst.private.version = '1.0';
inst.make  = 'BMW';
inst.model = 'x5';

for(prop in inst){
    if (prop==='private') continue;        // skip named property
    console.log(prop);
}

Using a different data model. The advantage is you can skip one property in the loop and because that property is an object, you can put any number of key/values in it.

How to hide properties of an object

Specific Case: Prototype vs Instance

Your example uses a prototype and an instance. Your version is a prototype property whereas make is an instance property. In this case JavaScript has a specific method to tell the two apart. For example:

car_instance.hasOwnProperty('make');  // returns true
car_instance.hasOwnProperty('version');  // returns false

However, what if you needed to hide an instance property? This is a more common case and there are several ways to answer your question thusly.

Dynamic hiding of object properties

We can use the old leading underscore naming trick to recognise hidden properties, such as _assessment.

Pro: No need for the code to 'know' the property names.

Con: This assumes you have control over the property names.

Con: Not all coders are comfortable with the idea of a leading underscore.

    // Prototype
    function Car(){
    }

    // Prototype properties...
    Car.prototype._version = '1.0.0';

    // Instance properties...
    var car_instance = new Car();
    car_instance.make = 'BMW';
    car_instance.model = 'x5';

    // Instance 'hidden' properties (with one leading underscore in name)...
    car_instance._assessment = '98%';

    // Display non-hidden instance properties
    for(property in car_instance){
       const visible = property[0] !== '_';
       if (visible) {
             document.body.innerHTML += property + '<br>';
       }
    }

Whitelist hiding of object properties

Alternatively we can maintain a list of properties to display. We'll omit hasOwnProperty in this one to show that we're relying completely on the whitelist.

Pro: You control exactly what is displayed.

Con: You must remember to add new fields to the whitelist.

    // Prototype
    function Car(){
    }

    // Prototype properties...
    Car.prototype.version = '1.0.0';
    Car.prototype.whitelist = ['make','model'];

    // Instance properties...
    var car_instance = new Car();
    car_instance.make = 'BMW';
    car_instance.model = 'x5';

    // Instance 'hidden' properties...
    car_instance.assessment = '98%';

    // Display non-hidden instance properties
    for(property in car_instance){
       const isVisible = Car.prototype.whitelist.includes(property);
       if (isVisible) {
             document.body.innerHTML += property + '<br>';
       }
    }

Blacklist hiding of object properties

Lastly we can maintain a list of properties to display.

Pro: You control exactly what is displayed.

Con: You must remember to add new hidden fields to the blacklist or they are immediately visible to everyone.

    // Prototype
    function Car(){
    }

    // Prototype properties...
    Car.prototype.version = '1.0.0';
    Car.prototype.blacklist = ['version', 'blacklist', 'assessment'];

    // Instance properties...
    var car_instance = new Car();
    car_instance.make = 'BMW';
    car_instance.model = 'x5';

    // Instance 'hidden' properties...
    car_instance.assessment = '98%';

    // Display non-hidden instance properties
    for(property in car_instance){
       const isHidden = Car.prototype.blacklist.includes(property);
       if (!isHidden) {
           document.body.innerHTML += property + '<br>';
       }
    }

There are other ways to achieve the same result, such as digging deeper into prototyping and classes.

本文标签: javascriptHow to hide properties of an objectStack Overflow