-
JavaScript에서 Priavate 구현Javascript 2020. 3. 15. 18:20
In its current state, there is no "direct” way to create a private variable in JavaScript.
-> 현재 상태에서 자바스크립트 private 변수를 (은닉화) 만드는 "직접적인" 방법은 없습니다.
In other languages, you can use the private keyword or double-underscores and everything works,
-> 다른 언어에서, private 키워드(자바 등) 또는 __ 이중 underscore 를 사용하는 등의 방법을 사용할 수 있지만
but variable privacy in JavaScript carries characteristics that make it seem more akin to an emergent trait of the language rather than an intended functionality.
-> JavaScript는 의도 된 기능보다는 언어의 특성과 더 유사하게 보이는 특성을 가지고 있습니다.* 더욱이 함수 스코프를 가지고 있는 "var"를 사용할 때는 이런 방법이 거의 불가능하다고 봤어도 된다고 봅니다.
// 글로벌 변수 a 선언 var a = 123; // 함수 스코프에 b선언 (function() { console.log(b); // 호이스팅 때문에 undefined 뜹니다. var b = 456; })(); console.log(a); // => 123 console.log(b); // 참조 예외 발생 (에러) // b는 함수형 스코프 밖에서 접근할 수 없기 때문입니다.
* es6의 탄생으로 인해서 블록 범위 스코프인 let과 const가 나오게 됩니다.
const a = 123; // 블록스코프 예시1 if (true) { const b = 345; } // 블록스코프 예시2 { const c = 678; } console.log(a); // 123 console.log(b); // 참조에러 블록스코프 밖에서 내부 변수 참조 불가 console.log(c); // 참조에러 블록스코프 밖에서 내부 변수 참조 불가
* 범위를 벗어난 코드는 변수에 액세스 할 수 없기 때문에 프라이버시의 특성을 얻습니다.
* 여러 가지 방법으로 구현하기위한 몇 가지 기술을 다룰 것입니다.
* JavaScript의 함수도 블록이므로 모든 가변 키워드가 작동합니다.
* 또한 "모듈"이라는 매우 유용한 디자인 패턴을 구현할 수 있습니다.
* 모듈 디자인 패턴은 공용 및 개인 구성 요소를 결합하고 프로그램을 더 작은 구성 요소로 나누고 "캡슐화"라는 프로세스를 통해 프로그램의 다른 부분에 액세스 할 수있는 부분 만 노출시키기 때문에 JavaScript에서 매우 유용합니다.
* 이 방법을 통해 우리는 사용해야 할 사항 만 공개하고 볼 필요가없는 나머지 구현을 숨길 수 있습니다.
* 이를 구현하기 위해 함수 범위를 활용할 수 있습니다.
const CarModule = () => { let milesDriven = 0; let speed = 0; const accelerate = (amount) => { speed += amount; milesDriven += speed; } const getMilesDriven = () => milesDriven; // "return" 키워드를 사용하여 무엇을 노출 시킬 지 숨길 지 결정할 수 있습니다. // 이 상황에서는 우리는 유일하게 accelerate() 함수와 getMilesDriven() 함수만을 노출시켜야합니다. return { accelerate, getMilesDriven } }; const testCarModule = CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven());
이 상황에서 private 변수에 대한 이점이 분명해지기 시작합니다.
변수, 함수 또는 기타 내부 구성 요소에 액세스하는 기능을 제거하면 의도하지 않은 것을 실수로 다른 사람이 실수로 사용하여 발생하는 오류의 표면적을 줄일 수 있습니다.
function CarModule() { let milesDriven = 0; let speed = 0; // CarModule을 참조하지않고 this 키워드를 사용합니다. this.accelerate = (amount) => { speed += amount; milesDriven += speed; } this.getMilesDriven = () => milesDriven; } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven());
* es6 CLASS를 사용한 방법
class CarModule { /* milesDriven = 0; speed = 0; */ constructor() { this.milesDriven = 0; this.speed = 0; } accelerate(amount) { this.speed += amount; this.milesDriven += this.speed; } getMilesDriven() { return this.milesDriven; } } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven());
* 언더스코어를 사용하는 방법도 있습니다.
* 밑줄 (_)로 변수 앞에 접두사를 붙이면 여전히 외부에 "표시"되지만 개발자에게 "이 변수를 만지지 마십시오." 라고 해줍니다.
/* _milesDriven = 0; _speed = 0; */ constructor() { this._milesDriven = 0; this._speed = 0; }
* 기술적으로, 클래스에서 변수 프라이버시를위한 메소드가 있습니다.
class CarModule { constructor() { let milesDriven = 0; let speed = 0; this.accelerate = (amount) => { speed += amount; milesDriven += speed; } this.getMilesDriven = () => milesDriven; } } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); console.log(testCarModule.speed); // undefined
* weakMap을 사용한 방법도 있습니다.
class CarModule { constructor() { this.data = new WeakMap(); this.data.set(this, { milesDriven: 0, speed: 0 }); } accelerate(amount) { // this keyword 대신에 weakMap을 사용합니다. const data = this.data.get(this); const speed = data.speed + amount; const milesDriven = data.milesDriven + data.speed; this.data.set({ speed, milesDriven }); } this.getMilesDriven = () => this.data.get(this).milesDriven; } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); console.log(testCarModule.data); //=> WeakMap { [items unknown] }
* 하지만 이 방법은 깊은 복사를 통해 새로운 CarModule을 선언하고 복사할 수 있으므로 실제로는 private이 아닙니다.
* 이것은 또 심볼을 사용하여 해결할 수 있습니다.
class CarModule { constructor() { this.speedKey = Symbol("speedKey"); this.milesDrivenKey = Symbol("milesDrivenKey"); this[this.speedKey] = 0; this[this.milesDrivenKey] = 0; } accelerate(amount) { this[this.speedKey] += amount; this[this.milesDrivenKey] += this[this.speedKey]; } getMilesDriven() { return this[this.milesDrivenKey]; } } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); console.log(testCarModule.speed); // => undefined
TC39 private class field proposal 라는 새로운 방법이 나왔습니다( 현재는 babel 사용하여 적용해야 함 )
단순하게 # 만 붙이면 됩니다.
class CarModule { #speed = 0 #milesDriven = 0 accelerate(amount) { this.#speed += amount; this.#milesDriven += speed; } getMilesDriven() { return this.#milesDriven; } } const testCarModule = new CarModule(); testCarModule.accelerate(5); testCarModule.accelerate(4); console.log(testCarModule.getMilesDriven()); console.log(testCarModule.speed); //=> undefined
출처 : https://css-tricks.com/implementing-private-variables-in-javascript/
'Javascript' 카테고리의 다른 글
SVG 모션 Path 그리기 (0) 2020.04.18 JS 이벤트 루프(callback, setTimeout, queue, 싱글스레드) (0) 2020.03.29 [이미지] Lazy Loading에 대한 고찰 (0) 2020.02.15 var, let & const 이해하기 (0) 2019.12.15 반복문 없이 반복문 하기 (0) 2019.09.14