How can I make private a javascript object property so that Object.keys()
and Object.getOwnPropertyNames()
don't return that property?

- 481
- 1
- 6
- 19
-
1By using the normal class declaration, I don't think that's possible. But there is [**other ways**](/questions/5140833/privateness-in-javascript) of declaring a class. – ibrahim mahrir Jul 16 '17 at 02:09
-
What is application? You could use `Proxy`. See also https://stackoverflow.com/questions/40386767/how-to-create-static-array-in-javascript/ – guest271314 Jul 16 '17 at 02:10
2 Answers
How can I make private a JavaScript object property so that
Object.keys()
andObject.getOwnPropertyNames()
don't return that property?
You're using the term "private", and then you're describing behavior which is different from that usually meant by that word.
"Private" normally means the property or value is not accessible from outside the object. Not being reported by Object.keys()
is referred to as being not enumerable.
Any property defined by defineProperty
will by default be not enumerable, so
Object.defineProperty(obj, 'privateField', {value: 5});
or, specifying it explicitly as in
Object.defineProperty(obj, 'privateField', {value: 5, enumerable: false});
will result in obj.privateField
being not enumerable, and thus not included in the results of Object.keys()
.
If you really want a property to be private in the usual sense--meaning it cannot be accessed from outside methods on the object--then some options include:
Use TypeScript and its
private
keyword. This will cause attempted external accesses to throw a compile-time error.Wait for JS enhancements for private fields, which may take the form
#foo
.Use a variable inside a closure to represent the private value.
Use symbols for the property name, although this might not ensure true privacy.
Use a
WeakMap
to represent the private property, as suggested in another answer.Wrap your object in a
Proxy
, as suggested in a comment, which interdicts access to the private property.
For more details and ideas, see this question.
-
A proxy sounds like a really bad idea - and how would it know whom to allow or deny access? – Bergi Jul 16 '17 at 04:38
Here's a demo of a class implementing private properties using a closure and a WeakMap:
const Private = function () {
const weakPrivateScope = new WeakMap()
return class Private {
constructor() {
weakPrivateScope.set(this, {})
}
get(propertyName) {
return weakPrivateScope.get(this)[propertyName]
}
set(propertyName, value) {
return weakPrivateScope.get(this)[propertyName] = value
}
has(propertyName) {
return Object.keys(weakPrivateScope.get(this)).includes(propertyName)
}
delete(propertyName) {
return delete weakPrivateScope.get(this)[propertyName]
}
}
}()
class MyClass extends Private {
constructor() {
super()
this.myPrivateProperty = 'initial value'
}
get myPrivateProperty() {
return this.get('myPrivateProperty')
}
set myPrivateProperty(value) {
return this.set('myPrivateProperty', value)
}
}
let myObject = new MyClass()
console.log('able to access and update value normally:')
console.log('myObject.myPrivateProperty')
console.log(myObject.myPrivateProperty)
console.log('myObject.myPrivateProperty = "new value"')
myObject.myPrivateProperty = 'new value'
console.log(myObject.myPrivateProperty)
console.log('keys() and getOwnPropertyNames() do not get the property:')
console.log(Object.keys(myObject))
console.log(Object.getOwnPropertyNames(myObject))
console.log('you can check for existence and delete the property as well:')
console.log('myObject.has("myPrivateProperty")')
console.log(myObject.has('myPrivateProperty'))
console.log('myObject.delete("myPrivateProperty")')
myObject.delete('myPrivateProperty')
console.log(myObject.has('myPrivateProperty'))

- 49,224
- 10
- 102
- 153
-
Note that this is possible in ECMAScript 5 as well, but it would have a memory leak unless you implemented a `destroy()` method on the class and called it before losing the reference to the object instance. – Patrick Roberts Jul 16 '17 at 02:43