有没有办法私有javascript对象属性?

时间:2017-07-16 02:02:55

标签: javascript object access-modifiers

如何将javascript对象属性设为私有,以便Object.keys()Object.getOwnPropertyNames()不返回该属性?

2 个答案:

答案 0 :(得分:3)

  

如何将JavaScript对象属性设为私有,以便Object.keys()Object.getOwnPropertyNames()不返回该属性?

您使用的是“私人”一词,然后您描述的行为与该词通常所指的行为不同。

“私有”通常表示无法从对象外部访问属性或值。 Object.keys()未报告的内容被称为enumerable

defineProperty定义的任何属性默认情况下都不可枚举,所以

Object.defineProperty(obj, 'privateField', {value: 5});

或,明确指定为

Object.defineProperty(obj, 'privateField', {value: 5, enumerable: false});

会导致obj.privateField无法枚举,因此不会包含在Object.keys()的结果中。

如果你真的希望一个属性在通常意义上是私有的 - 意味着它不能从对象的外部方法访问 - 那么一些选项包括:

  1. 使用TypeScript及其private关键字。这将导致尝试外部访问引发编译时错误。

  2. 等待private fields的JS增强功能,其格式可能为#foo

  3. 在闭包内使用变量来表示私有值。

  4. 使用符号作为属性名称,但这可能无法确保真正的隐私。

  5. 使用WeakMap代表私人财产,如另一个答案所示。

  6. 根据评论中的建议将您的对象包裹在Proxy中,该评论会阻止对私有财产的访问。

  7. 有关详情和想法,请参阅this question

答案 1 :(得分:2)

这是使用闭包和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'))