ES6私有变量与babel的爱情碰撞

2021-01-21 15:12:57 浏览数 (1)

私有变量

JS原生不支持私有变量,这让前端开发很头痛,如何实现私有变量对于程序的健壮十分重要。下面就讲下私有变量的几种实现,以及对应的babel插件。

主要是讲ES6相关的SymbolWeakMap,当然闭包也是可以实现的,本篇主要讲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新的私有属性/方法的提案,在私有属性、方法前面加上#来标识。下面是对应的写法

代码语言:javascript复制
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

最后对比下SymbolWeakMap的使用,其实两者都实现了私有,并不想_只是一个标记而已(感觉就像babel里的设置为trueloose选项一样)。 对比二者的兼容性,感觉也没多大的区别,对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

0 人点赞