专栏名称: 冴羽
公众号 @ 冴羽的JavaScript博客
目录
相关文章推荐
鸡西新闻网  ·  【夜读】谢谢你爱我! ·  8 小时前  
广东公共DV现场  ·  有游客失联!知名景区通报 ·  9 小时前  
广东公共DV现场  ·  视频曝光!男子在广州街头“翘头”飙车,时隔两 ... ·  9 小时前  
广东台今日关注  ·  深圳放大招:可免费住15天 ·  13 小时前  
51好读  ›  专栏  ›  冴羽

ES6 系列之私有变量的实现

冴羽  · 掘金  ·  · 2018-11-20 14:28

正文

阅读 168

ES6 系列之私有变量的实现

前言

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

1. 约定

实现

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

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // private
复制代码

优点

  1. 写法简单
  2. 调试方便
  3. 兼容性好

缺点

  1. 外部可以访问和修改
  2. 语言没有配合的机制,如 for in 语句会将所有属性枚举出来
  3. 命名冲突

2. 闭包

实现一

/**
 * 实现一
 */
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
复制代码

优点

  1. 无命名冲突
  2. 外部无法访问和修改

缺点

  1. constructor 的逻辑变得复杂。构造函数应该只做对象初始化的事情,现在为了实现私有变量,必须包含部分方法的实现,代码组织上略不清晰。
  2. 方法存在于实例,而非原型上,子类也无法使用 super 调用
  3. 构建增加一点点开销

实现二

/**
 * 实现二
 */
const Example = (function() {
  var _private = '';

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

  return Example;

})();

var ex = new Example();

console.log(ex.getName()); // private
console.log(ex._private); // undefined
复制代码

优点

  1. 无命名冲突
  2. 外部无法访问和修改

缺点

  1. 写法有一点复杂
  2. 构建增加一点点开销

3. Symbol

实现

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
复制代码

优点

  1. 无命名冲突
  2. 外部无法访问和修改
  3. 无性能损失

缺点

  1. 写法稍微复杂
  2. 兼容性也还好

4. WeakMap

实现

/**
 * 实现一
 */
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
复制代码

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

/**
 * 实现二
 */
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
复制代码

优点

  1. 无命名冲突
  2. 外部无法访问和修改

缺点

  1. 写法比较麻烦
  2. 兼容性有点问题
  3. 有一定性能代价

5. 最新提案

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 字段呢?比如说这样:

class Foo {
  private value;

  equals(foo) {
    return this.value === foo.value;
  }
}
复制代码

简单点来说,就是嫌麻烦,当然也有性能上的考虑……







请到「今天看啥」查看全文


推荐文章
鸡西新闻网  ·  【夜读】谢谢你爱我!
8 小时前
广东公共DV现场  ·  有游客失联!知名景区通报
9 小时前
广东台今日关注  ·  深圳放大招:可免费住15天
13 小时前
老罗话指数投资  ·  投资大师的5条投资原则
7 年前