为了账号安全,请及时绑定邮箱和手机立即绑定

EcmaScript2015(ES6)中如何定义私有变量

标签:
JavaScript

自从世界从ES5转到ES6,为了让JavaScript代码库更加美观,ES语法(不仅是语法)发生了巨大的变化。尽管其他所有语法都有所改进,但有一件令开发人员困扰的事情是,如何在类中声明私有变量。但不幸的是,在ES6中没有专门的语法。

没有!ES6中没有专门的语法来声明私有变量。不过有一个提案

新提案(还没有实现)

class  MyClass{  #private1;
  #private2;
  getPrivate1(){    return  this.private1;
  }
}

上面的语法是提交给TC39的一个提案,还没被批准,并且在不久的将来肯定也不能用,但我们希望在未来的一些ES版本中可以有这种语法。

声明私有变量的最佳方式

你可以创建模块,而模块中的所有东西都是私有的,直到以及除非你使用exports公开它。

let private1  =  new  WeakMap();
let private2  =  new  WeakMap();class  MyClass {  constructor() {    this.setPrivate1("something");
    private2.set(this,  "something else");
  }

  getPrivate1() {    return  private1.get(this);//"something"
  }

  getPrivate2() {    return  private2.get(this);//"something else"
  }

  setPrivate1(val) {
    private1.set(this,  val);
  }
}

module.exports  =  MyClass;

为什么不用let private1 = “something”; 这种方式

为什么我们不声明一个变量private1,然后将它所需的值赋给它呢?原因是,变量private1是一个会在MyClass的所有实例中共享的单一变量。所以只要有任何一个实例修改了private1,那么同样的变化就会反映到其它实例上。

为什么是用WeakMap而不是Map?

Map和WeakMap之间的区别在于:对于WeakMap来说,如果键对象准备好被垃圾回收,就会自动删除值;而对于Map来说,它会一直维持一个对键对象的引用,从而会导致内存泄漏。

声明私有变量的其它方式

还有其它几种方式来声明私有变量,每种方式各有其优缺点。其中的两种方式描述如下。

命名约定

多年来人们一直在私有变量的名称中使用下划线。如果你根据这个约定,并且信任其他开发人员的话,就可以用这种方法。不过,这并不能确保数据的安全性,因为任何人如果想的话,他可以用或者甚至修改该数据。如果你正在开发一个库,那么这种方法强烈不推荐。

class  MyClass {  constructor() {    this._private1  =  "something";    this.public  =  "something else";
  }
}

Object.assign

通过用Object.assign,你也能使用私有变量,并且能确保数据安全。但是这种方法的问题是,要读写该私有变量的方法不能是原型方法。这些方法与私有变量一起,也必须写在构造器内。这不仅让它对于其他开发人员来说很难去读懂,而且也是一种低效率的声明那个函数的方式;因为这些函数会被在该类的每个实例中重复(不是共享)。

class  MyClass{  constructor(){    var  private1  =  "something";
    Object.assign(this,  {
      getPrivate(){        return  private1;
      },
      setPrivate(val){
        private1  =  val;
      }
    });
  }

  anotherMethod(){
    console.log(private1);  //ERROR
  }
}

结论

有些人可能会推荐用ES6 Symbol来创建私有变量。几个月前这种方式还是有效的,不过ES6已经修改了其草案,现在Symbol键从一个对象的外部也可以访问了。所以遵循这种方式没有意义。不过,最佳实践是把你的程序分为模块,并且用我展示的第一个方式来声明私有变量。使用这种方式能确保数据安全,该类中所有方法将都能访问该数据。我所看到的唯一缺点是,它给了你一种骇客式的感觉,因为与命名约定方式中相比,私有变量与类没有太大关系。

相关帖子

  1. [ES6 Map vs WeakMap vs plain Objects – Describing the differences][55]

  2. [Clone an object in vanilla JS – multiple ways][56]

  3. [Understanding Ember Objects, computed properties and observers – Ember.js Tutorial part 4][57]

译文出处

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消