# javascript中控制对象属性访问
在javascript中,没有私有变量(闭包除外),我们随时可以增删改查某个对象的属性,某些重要的变量被人随意修改这样并不太好。 javascript中有几种控制对对象属性的访问方式,getter和setter,类似于java中的对对象的封装类。
# 字面量get、set
定义
// 添加get和set
const person = {
name: 'susan',
get userName() {
return this.name
},
set userName(value){
this.name = value
},
gender: 'woman',
get userGender() {
return this.gender
},
set userGender(value) {
this.gender = value
}
}
使用
assert(person.userName === 'susan', 'get name ' + person.userName)
person.userName = 'lily'
assert(person.userName === 'lily', 'get name ' + person.userName)
# ES6中
定义
class Person{
constructor(name){
this.name = name
}
get userName(){
return this.name = name
}
set userName(value){
this.name = value
}
}
使用
const p1 = new Person('susan', 'hong')
assert(p1.userName === 'susanhong', 'get name') // pass
assert(p1.name === 'susanhong', 'get name') // fail
p1.userName = 'jack'
assert(p1.userName === 'jack', 'get myName ' + p1.userName) // pass
# Object.defineProperty定义私有变量
定义
function Person() {
// 私有变量
let _name = 'susan'
// 定义对外变量
Object.defineProperty(this, 'name', {
get: () => {
return _name
},
set: (value) => {
_name = value
}
})
}
使用
const s1 = new Student()
assert(typeof s1._name === 'undefined', '无法访问私有变量') // pass
assert(s1.name === 'susan', '通过接口访问私有变量') // pass
# 使用代理Proxy构建私有属性
定义
const person = {
name: 'susan',
age: 18
}
const personProxy = new Proxy(person, {
get: (target, key) => {
// 可在此做一些日志记录
report(`reading property ${key}: ${target[key]}`)
return target[key]
},
set: (target, key, value) => {
// 日志记录
report(`writing property ${key}: ${value}`)
target[key] = value
}
})
使用
assert(person.job === undefined, 'person.job is undefined') // pass
assert(personProxy.name === 'susan', 'personProxy.name is susan') // pass
personProxy.name = 'lily'
assert(personProxy.name === 'lily', 'personProxy.name is lily') // pass
// 通过代理对象分配新的属性
personProxy.job = 'programmer'
assert(person.job === undefined, `person.job is ${person.job}`) // fail