이 글은 ES6의 비공개 변수 구현에 대한 요약(코드 예제)을 제공합니다. 이는 특정 참조 값을 가지고 있으므로 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
"ECMAScript 6 소개"를 읽으면서 프라이빗 변수의 구현이 흩어져 있는 것을 보았으므로 여기에 요약하겠습니다.
class Example { constructor() { this._private = 'private'; } getName() { return this._private } } var ex = new Example(); console.log(ex.getName()); // private console.log(ex._private); // private
간단한 작성 방법
쉬운 디버깅
호환성
외부인이
언어에 액세스하고 수정할 수 있습니다. 모든 속성을 열거하는 in in 문과 같은 일치하는 메커니즘은 없다 접근 및 수정 불가
단점
구성으로 인해 약간의 오버헤드가 추가됩니다.
구현 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
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
장점
외부 접근 및 수정 불가
성능 손실 없음
호환성도 좋음
4.약한 지도
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
이렇게 쓰면 캡슐화가 부족하다고 느낄 수도 있으니 이렇게 써도 됩니다:
/** * 实现一 */ 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
일정한 성능 비용이 있음
5. 최신 제안은
/** * 实现二 */ 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
class Point { #x; #y; constructor(x, y) { this.#x = x; this.#y = y; } equals(point) { return this.#x === point.#x && this.#y === point.#y; } }
class Foo { private value; equals(foo) { return this.value === foo.value; } }
여기서 create new 두 개의 인스턴스가 생성된 후 foo2가 foo1의 인스턴스 메소드에 매개변수로 전달됩니다.
foo2.value
를 직접 호출하면 당연히 값을 얻을 수 없겠죠. 결국 private 변수인데 Equals는 Foo의 클래스 메소드이므로 얻을 수 있을까요? 답은 그렇습니다.
값을 가져오는 것이 괜찮으므로 인쇄된 결과는 true여야 하지만, 우리가 전달한 값이 Foo의 인스턴스가 아니라 다른 객체라면 어떻게 될까요?
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.value
肯定是获取不到值的,毕竟是私有变量,可是 equals 是 Foo 的一个类方法,那么可以获取到的吗?
答案是可以的。
其实这点在其他语言,比如说 Java 和 C++ 中也是一样的,类的成员函数中可以访问同类型实例的私有变量,这是因为私有是为了实现“对外”的信息隐藏,在类自己内部,没有必要禁止私有变量的访问,你也可以理解为私有变量的限制是以类为单位,而不是以对象为单位,此外这样做也可以为使用者带来便利。
既然获取值是可以的,那么打印的结果应该为 true,但是如果我们传入的值不是 Foo 的实例,而是一个其他对象呢?
var foo1 = new Foo(); console.log(foo1.equals({ value: 2 }));
当然这里代码也是可以正常运行的,但是对于编译器来说,就有一点麻烦了,因为编译器不知道 value 到底是 foo 的正常属性还是私有属性,所以编译器需要做判断,先判断 foo 是不是 Foo 的实例,然后再接着获取值。
这也意味着每次属性访问都需要做这样一个判断,而引擎已经围绕属性访问做了高度优化,懒得改,而且还降低速度。
不过除了这个工作之外,还会有一些其他的内容需要考虑,比如说:
你必须将私有的 key 编码进每个词法环境
for in 可以遍历这些属性吗?
私有属性和正常属性同名的时候,谁会屏蔽谁?
怎么防止私有属性的名称不被探测出来。
关于使用 # 而不使用 private 更多的讨论可以参考这个 Issue。
当然这些问题都可以被解决啦,就是麻烦了点。
而如果你选择 #,实现的方式将跟 JavaScript 对象属性完全没有关系,将会使用 private slots
비공개 슬롯
방법을 사용하고 간단히 말해서 더 좋습니다. 개인 구현보다 방법이 훨씬 간단합니다. 🎜🎜🎜위 내용은 ES6의 개인 변수 구현 요약(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!