title: 私有变量 tags: [JavaScript手写题]
私有变量
通常,私有属性有一个约定,例如以_
开头的属性是私有属性变量,我们不能对这一类成员访问和操作。
在以前的JavaScript是没有私有属性的说法,但像函数内部,块级作用域中的变量可以并认为是私有的,因为外部无法访问到它,
ES提案
后来有个类私有属性的提案,让JavaScript
可以直接在类中成员属性前面追加#
,代表它是私有属性。
js
class Foo{
#bar = 0;
}
bar为私有变量
Class field declarations for JavaScript
Proxy
通过Proxy
对象拦截私有属性的获取操作
js
function proxy(obj) {
return new Proxy(obj, {
get(target, key) {
if (/^_/.test(key)) {
throw new Error(`${key} is private`)
} else {
return target[key]
}
},
set(target, key) {
if (/^_/.test(key)) {
throw new Error(`${key} is private, cannot be modified`)
}
},
// 遍历时拦截处理
ownKeys(target) {
return target.ownKeys(target).filter(key => !!!/^_/.test(key))
}
})
}
console.log(fooProxy) // {name: 'island', _age: 18}
console.log(fooProxy.name) // island
console.log(fooProxy._age) // Error: _age is private
Symbol
利用Symbol
标签的唯一性,将带_
开头的属性替换成symbolKey
,使得外部无法访问。
js
function sym(obj) {
const result = {}
for (const key in obj) {
if (/^_/.test(key)) {
const symbolKey = Symbol(key)
result[symbolKey] = obj[key]
} else {
result[key] = obj[key]
}
return result
}
}
const fooSym = sym({ name: 'island', _age: 18 })
console.log(fooSym) // {name: 'island'}
closure
利用闭包的特性,内部可以访问得到私有属性,返回给外部一个不带私有属性的对象。
js
const closure = function (obj) {
return (function () {
console.log(Object.keys(obj).filter(i => /^_/.test(i)))
return Object.keys(obj).filter(i => !/^_/.test(i))
})()
}
const fooClo = closure({ name: 'island', _age: 18 })
console.log(fooClo) // {name: 'island'}