public 필드는 클래스 내부, 자식 클래스 내부, 클래스 인스턴스를 통한 접근이 모두 허용된다.
private 필드는 클래스 내부에서만 접근이 가능하다.
즉, private 필드는 클래스 외부에서 직접 접근할 수 있는 방법은 없다. 다만 접근자 프로퍼티를 통해 간접적으로 접근하는 방법이 유효하다. 따라서 데이터를 조금 더 안전하게 보관할 수 있다.
접근 제어자를 지원하지 않는 과거 JS에서는 언더바(_)를 붙이는 컨벤션으로 private 변수, 메서드를 구분했었다.
2008년에 더글라스 크락포드가 제안했지만, 최근에는 지양하자는 이야기가 많다. 이유가 무엇인지 알아보자!
나이스 샵(#)
#
즉 샵 프리픽스를 사용한다. 키워드가 아니라 프리픽스다. 속성 명 앞에 #
이 붙으면 Private 필드로 동작한다.#foo
자체만 식별자로 허용되고 #[fooName]
이건 문법 오류다.모든 Private 필드는 소속된 클래스에 고유한 스코프를 갖는다.
간단하게 #
프리픽스를 이용해서 Human 클래스에 #age
속성을 만들고 외부에서 접근해보자.
class Human {
#age = 10;
}
const person = new Human();
console.log(person.#age); // Error : Property '#age' is not accessible outsied class 'Human' because it has a private identifier
#
은 키워드가 아니라 프리픽스다. #
없이는 해당 클래스 내부에서도 접근할 수 없다.
class Human {
#age = 10;
getAge() {
return this.age; // Error : Property 'age' does not exist on type 'Human'. Did you mean '#age'?
}
}
정상적으로 private 속성을 클래스에서 정의하고 사용해보자.
class Human {
#age = 10;
getAge() {
return this.#age;
}
}
const person = new Human();
console.log(person.getAge()); // 10
외부의 getAge()라는 getter를 노출해 #age 값에 접근할 수 있게 했다.
class Human {
#age = 10;
getAge() {
return this.#age;
}
}
class Person extends Human {
#age = 20;
getFakeAge() {
return this.#age;
}
}
const p = new Person();
console.log(p.getAge()); // 10
console.log([.getFakeAge()]); // 20
자바스크립트의 private 속성은 독특한 특징이 있다.
"모든 Private 필드는 소속된 클래스에 고유한 스코프를 갖는다."
#age 즉, private 속성은 그동안 우리가 알고 있던 this의 그 컨텍스트와는 다른 방식으로 저장된다. 기존처럼 인스턴스 별로 독립적인 공간을 갖지만, 추가로 클래스 별로 독립적인 공간을 갖는 것이다.
쉽게 말하면 Human 클래스 스코프의 #age와 Person 클래스 스코프의 #age는 다르다는 것이다. 그러므로 Human 클래스에 속한 getAge()가 실행될 때는 Human의 #age에 접근하고 Person의 getFakeAge()가 실행될 때는 Person의 #age에 접근하는 것이다.
바로 그게 "모든 Private 필드는 소속된 클래스에 고유한 스코프를 갖는다."라는 문장의 의미다.
참고 링크 : 은닉을 향한 자바스크립트의 여정