Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

WeakMap 与 Symbol 的选择

  WeakMap 和 Symbol 其实是同类的东西,但它们的概念都是让一个对象去绑定一个堆。不同在于它们的使用形式,WeakMap 是统一管理一组元素的堆,而 Symbol 是在元素上,以匿名属性的形式来管理。但由于 Symbol 的种种坑爹性质,我毅然地选择了 WeakMap。
  如果想给一个对象添加一个私有属性,大家都会约定俗成地使用前缀命名的方式。这么做虽然可以减少冲突,但无法避免,而且也暴露了接口。 <script>
var F;
void function(){
  F=function(){};
  F.prototype.fuck=function(){
    // 这里的 _i 就是私有属性
    this._i=this._i||1;
    console.log(this._i++);
  };
}();

// 每个实例都有一个自己的计数器
var f = new F;
f.fuck();
f.fuck();

// 但是私有属性就直接暴露了
f._i=100;
f.fuck();
</script>
  这是一个很烂的封装!于是我们来试试 Symbol。 <script>
var F;
void function(){
  var I=Symbol();
  F=function(){};
  F.prototype.fuck=function(){
    // 这里的 I 就是私有属性
    this[I]=this[I]||1;
    console.log(this[I]++);
  };
}();

// 每个实例都有一个自己的计数器
var f = new F;
f.fuck();
f.fuck();

// 但是私有属性直接暴露了
var s=Object.getOwnPropertySymbols(f);
f[s[0]]=100;
f.fuck();
</script>
  Symbol 也会暴露了私有属性,只是获取的方法比较绕而已。所以这同样也是很烂的封装。不过 V8 内部有个 PrivateSymbol 的概念,它无法从外部被取到。但这个在 ES6 里是没戏了,ES7 不知道会不会引入。要是有的话,这才是最佳方案。最后我们来看看目前的最佳方案 WeakMap。 <script>
var F;
void function(){
  var map=new WeakMap();
  F=function(){
    // 申请一个堆
    map.set(this,{});
  };
  F.prototype.fuck=function(){
    // 获取堆引用
    var heap=map.get(this);
    // 在堆中存储数据并处理
    heap.i=heap.i||1;
    console.log(heap.i++);
  };
}();

// 每个实例都有一个自己的计数器
var f = new F;
f.fuck();
f.fuck();

// 外部已经没有任何途径来获取或修改私有的 i
</script>
网名:
3.84.186.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^