前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >ES6 系列之私有变量的实现

ES6 系列之私有变量的实现

作者头像
腾讯NEXT学位
修改2019-08-05 15:33:21
5530
修改2019-08-05 15:33:21
举报
文章被收录于专栏:腾讯NEXT学位腾讯NEXT学位

在阅读 《ECMAScript 6 入门》的时候,零散的看到有私有变量的实现,所以在此总结一篇。

约定

1

实现

代码语言:javascript
复制
class Example {
    constructor() {
        this._private = 'private';
    }
    getName() {
        return this._private
    }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // private

2

优点

1.写法简单

2.调试方便

3.兼容性好

3

缺点

1.外部可以访问和修改

2.语言没有配合的机制,如 for in 语句会将所有属性枚举出来

3.命名冲突

闭包

1

实现

代码语言:javascript
复制
/**
 * 实现一
 */
class Example {
  constructor() {
    var _private = '';
    _private = 'private';
    this.getName = function() {return _private}
  }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // undefined

2

优点

1.无命名冲突

2.外部无法访问和修改

3

缺点

1.constructor 的逻辑变得复杂。构造函数应该只做对象初始化的事情,现在为了实现私有变量,必须包含部分方法的实现,代码组织上略不清晰

2.方法存在于实例,而非原型上,子类也无法使用 super 调用

3.构建增加一点点开销

symbol

1

实现

代码语言:javascript
复制
const Example = (function() {
    var _private = Symbol('private');

    class Example {
        constructor() {
          this[_private] = 'private';
        }
        getName() {
          return this[_private];
        }
    }

    return Example;
})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

2

优点

1.无命名冲突

2.外部无法访问和修改

3.无性能损失

3

缺点

1.写法稍微复杂

2.兼容性也还好

weakmap

1

实现

代码语言:javascript
复制
/**
 * 实现一
 */
const _private = new WeakMap();

class Example {
  constructor() {
    _private.set(this, 'private');
  }
  getName() {
    return _private.get(this);
  }
}

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

如果这样写,你可能觉得封装性不够,你也可以这样写:

代码语言:javascript
复制
/**
 * 实现二
 */
const Example = (function() {
  var _private = new WeakMap(); // 私有成员存储容器

  class Example {
    constructor() {
      _private.set(this, 'private');
    }
    getName() {
        return _private.get(this);
    }
  }

  return Example;
})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex.name); // undefined

2

优点

1.无命名冲突

2.外部无法访问和修改

3

缺点

1.写法比较麻烦

2.兼容性有点问题

3.有一定性能代价

最新提案

1

实现

代码语言:javascript
复制
class Point {
  #x;
  #y;

  constructor(x, y) {
    this.#x = x;
    this.#y = y;
  }

  equals(point) {
    return this.#x === point.#x && this.#y === point.#y;
  }
}

那么为什么不直接使用 private 字段呢?比如说这样:

代码语言:javascript
复制

class Foo {
  private value;

  equals(foo) {
    return this.value === foo.value;
  }
}

这样写不仅比较麻烦,而且也有性能上的考虑……

举个例子,如果我们不使用 #,而是使用 private 关键字:

代码语言:javascript
复制
class Foo {
  private value = '1';

  equals(foo) {
    return this.value === foo.value;
  }
}

var foo1 = new Foo();
var foo2 = new Foo();

console.log(foo1.equals(foo2));

在这里我们新建了两个实例,然后将 foo2 作为参数传入了 foo1 的实例方法中。

那么我们可以获取 foo2.value 的值吗?如果我们直接 foo2.value 肯定是获取不到值的,毕竟是私有变量,可是 equals 是 Foo 的一个类方法,那么可以获取到的吗?

答案是可以的。

结束语

其实这点在其他语言,比如说 Java 和 C++ 中也是一样的,类的成员函数中可以访问同类型实例的私有变量,这是因为私有是为了实现“对外”的信息隐藏,在类自己内部,没有必要禁止私有变量的访问,你也可以理解为私有变量的限制是以类为单位,而不是以对象为单位,此外这样做也可以为使用者带来便利。

原文地址:

https://zhuanlan.zhihu.com/p/50450255

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 腾讯NEXT学院 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档