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;
  }
}

简朴点来讲,就是嫌贫苦,固然也有机能上的斟酌……

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

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++ 中也是一样的,类的成员函数中能够接见同范例实例的私有变量,这是由于私有是为了完成“对外”的信息隐蔽,在类本身内部,没有必要制止私有变量的接见,你也能够明白为私有变量的限定是以类为单元,而不是以对象为单元,另外如许做也能够为运用者带来方便。

既然猎取值是能够的,那末打印的效果应当为 true,然则假如我们传入的值不是 Foo 的实例,而是一个其他对象呢?

var foo1 = new Foo();

console.log(foo1.equals({
  value: 2
}));

固然这里代码也是能够一般运转的,然则关于编译器来讲,就有一点贫苦了,由于编译器不知道 value 究竟是 foo 的一般属性照样私有属性,所以编译器须要做推断,先推断 foo 是否是 Foo 的实例,然后再接着猎取值。

这也意味着每次属性接见都须要做如许一个推断,而引擎已缭绕属性接见做了高度优化,懒得改,而且还下降速率。

不过除了这个事情以外,还会有一些其他的内容须要斟酌,比如说:

  1. 你必需将私有的 key 编码进每一个词法环境
  2. for in 能够遍历这些属性吗?
  3. 私有属性和一般属性同名的时刻,谁会屏障谁?
  4. 怎样防备私有属性的称号不被探测出来。

关于运用 # 而不运用 private 更多的议论能够参考这个 Issue

固然这些题目都能够被处置惩罚啦,就是贫苦了点。

而假如你挑选 #,完成的体式格局将跟 JavaScript 对象属性完整没有关系,将会运用 private slots 的体式格局以及运用一个新的 slot 查找语法,总之就是会比 private 的完成体式格局简朴许多。

参考

  1. 《编程言语怎样演变——以JS的private为例》贺师俊
  2. Exploring ES6
  3. 译 JS 新语法:私有属性

ES6 系列

ES6 系列目次地点:https://github.com/mqyqingfeng/Blog

ES6 系列估计写二十篇摆布,旨在加深 ES6 部份知识点的明白,重点解说块级作用域、标签模板、箭头函数、Symbol、Set、Map 以及 Promise 的模仿完成、模块加载计划、异步处置惩罚等内容。

本文作者:冴羽

浏览原文

本文为云栖社区原创内容,未经许可不得转载。

    原文作者:阿里云云栖社区
    原文地址: https://segmentfault.com/a/1190000017171028
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞