私有变量
JS原生不支持私有变量,这让前端开发很头痛,如何实现私有变量对于程序的健壮十分重要。下面就讲下私有变量的几种实现,以及对应的babel插件。
主要是讲ES6相关的Symbol
和WeakMap
,当然闭包也是可以实现的,本篇主要讲es6的。
Symbol
原生实现
代码语言:javascript复制let _method = Symbol('_method');
class Foo {
constructor() {
this[_method]();
}
[_method]() {
// ...
}
}
复制代码
babel插件实现
babel-plugin-private-underscores
插件自动处理下划线开头的属性与方法,换成Symbol类型的变量
代码语言:javascript复制class Foo {
constructor() {
this._method();
}
_method() {
// ...
}
}
复制代码
WeakMap
原生实现
代码语言:javascript复制const _private = new WeakMap();
class Foo {
constructor() {
_private.set(this, 'foo');
}
getPrivate() {
return _private.get(this);
}
}
let foo = new Foo();
console.log(foo.getPrivate()); // private
复制代码
babel官方插件实现
我们使用babel官方的插件@babel/plugin-proposal-private-methods
, 链接。
babel官方插件是JS新的私有属性/方法的提案,在私有属性、方法前面加上#
来标识。下面是对应的写法
class Foo {
constructor() {
this.publicField = this.#privateMethod();
}
#privateMethod() {
return 42;
}
}
babel-plugin-transform-private-properties
babel-plugin-transform-private-properties插件的写法如下:
代码语言:javascript复制class Private_Property_Class_With_WeakMap {
@Private
p = 'foo'
getP() {
return this.p
}
@Private
private_func () {
console.log('this's a private function')
}
}
let ppw = new Private_Property_Class_With_WeakMap()
console.log(ppw.getP()) // => foo
console.log(ppw.p) // => undefined
ppw.private_func() // Error: ppw.private_func is not a function
复制代码
babel产物可见babel try it out,需要自己手动加下plugin
babel-plugin-transform-private-properties,在右下角Plugins
处添加即可
Final
最后对比下Symbol
与WeakMap
的使用,其实两者都实现了私有,并不想_
只是一个标记而已(感觉就像babel
里的设置为true
的loose
选项一样)。 对比二者的兼容性,感觉也没多大的区别,对IE有兼容性的就打消使用的想法了。 在nodejs上使用倒还是可以的。
Symbol
的浏览器兼容性,来源来自mdn
IE | Chrome | Edge | Safari | Android Webview | ios Safari | nodejs |
---|---|---|---|---|---|---|
11 | 38 | 12 | 9 | 38 | 9 | 0.12 |
WeakMap
的浏览器兼容性,来源来自mdn
IE | Chrome | Edge | Safari | Android Webview | ios Safari | nodejs |
---|---|---|---|---|---|---|
11 | 36 | 12 | 8 | 37 | 8 | 0.12 |