도찐개찐
[Javascript] private variable 본문
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://frontdev.tistory.com/entry/JavaScript에서-Priavate-변수-구현 [Front End Develop]
'Javascript' 카테고리의 다른 글
[javascript] 자바스크립트 물음표 2개 / 느낌표 2개 / 물결(~) 2개 연산자 (0) | 2023.11.21 |
---|---|
[Javascript] 지역 선택 셀렉트 박스 (0) | 2022.06.20 |
[Javascript] For VS forEach VS map (0) | 2022.04.25 |
[Javascript VS ES6] 화살표 함수(Arrow Function) (0) | 2022.04.25 |
[Javascript VS ES6] Prototype vs Class (0) | 2022.04.25 |