diff options
Diffstat (limited to 'files/ko/web/javascript/reference/classes')
6 files changed, 1375 insertions, 0 deletions
diff --git a/files/ko/web/javascript/reference/classes/class_fields/index.html b/files/ko/web/javascript/reference/classes/class_fields/index.html new file mode 100644 index 0000000000..959c65fada --- /dev/null +++ b/files/ko/web/javascript/reference/classes/class_fields/index.html @@ -0,0 +1,396 @@ +--- +title: Class fields +slug: Web/JavaScript/Reference/Classes/Class_fields +translation_of: Web/JavaScript/Reference/Classes/Public_class_fields +--- +<div>{{JsSidebar("Classes")}}</div> + +<div class="note"> +<p><strong>This page describes experimental features.</strong></p> + +<p>Both Public and private field declarations are an <a href="https://github.com/tc39/proposal-class-fields">experimental feature (stage 3)</a> proposed at <a href="https://tc39.github.io/beta/">TC39</a>, the JavaScript standards committee.</p> + +<p>Support in browsers is limited, but the feature can be used through a build step with systems like <a href="https://babeljs.io/">Babel</a>. See the <a href="#Browser_compatibility">compat information</a> below.</p> +</div> + +<h2 id="Public_fields">Public fields</h2> + +<p>static fields와 instance의 public fields 는 둘 다 writable, enumerable, configurable 한 프로퍼티들이다. 예를들면, 정 반대인 private 과는 다르게, unlike their private counterparts, static fields는 프로토타입 상속에 관여한다.</p> + +<h3 id="Public_static_fields">Public static fields</h3> + +<p>Public static fields 는 클래스에서 생성하는 모든 인스턴스에 대한 필드가 아닌, 클래스마다 단 한개의 필드가 존재하기를 원할 때 유용하게 사용할 수 있다. Public fields는 캐시, 고정된 설정값, 또는 인스턴스 간 복제할 필요가 없는 어떤 데이터 등에 유용하게 쓰일 수 있다.</p> + +<p>Public static fields are declared using the <code>static</code> keyword. They are added to the class constructor at the time of class evaluation using {{jsxref("Global_Objects/Object/defineProperty", "Object.defineProperty()")}}. They are accessed again from the class constructor.</p> + +<pre class="brush: js">class ClassWithStaticField { + static staticField = 'static field' +} + +console.log(ClassWithStaticField.staticField) +// expected output: "static field" +</pre> + +<p>Fields without initializers are initialized to <code>undefined</code>.</p> + +<pre class="brush: js">class ClassWithStaticField { + static staticField +} + +console.assert(ClassWithStaticField.hasOwnProperty('staticField')) +console.log(ClassWithStaticField.staticField) +// expected output: "undefined"</pre> + +<p>Public static fields are not reinitialized on subclasses, but can be accessed via the prototype chain.</p> + +<pre class="brush: js">class ClassWithStaticField { + static baseStaticField = 'base field' +} + +class SubClassWithStaticField extends ClassWithStaticField { + static subStaticField = 'sub class field' +} + +console.log(SubClassWithStaticField.subStaticField) +// expected output: "sub class field" + +console.log(SubClassWithStaticField.baseStaticField) +// expected output: "base field"</pre> + +<p>When initializing fields, <code>this</code> refers to the class constructor. You can also reference it by name, and use <code>super</code> to get the superclass constructor (if one exists).</p> + +<pre class="brush: js">class ClassWithStaticField { + static baseStaticField = 'base static field' + static anotherBaseStaticField = this.baseStaticField + + static baseStaticMethod() { return 'base static method output' } +} + +class SubClassWithStaticField extends ClassWithStaticField { + static subStaticField = super.baseStaticMethod() +} + +console.log(ClassWithStaticField.anotherBaseStaticField) +// expected output: "base static field" + +console.log(SubClassWithStaticField.subStaticField) +// expected output: "base static method output" +</pre> + +<h3 id="Public_instance_fields">Public instance fields</h3> + +<p>Public instance fields exist on every created instance of a class. By declaring a public field, you can ensure the field is always present, and the class definition is more self-documenting.</p> + +<p>Public instance fields are added with {{jsxref("Global_Objects/Object/defineProperty", "Object.defineProperty()")}} either at construction time in the base class (before the constructor body runs), or just after <code>super()</code> returns in a subclass.</p> + +<pre class="brush: js">class ClassWithInstanceField { + instanceField = 'instance field' +} + +const instance = new ClassWithInstanceField() +console.log(instance.instanceField) +// expected output: "instance field"</pre> + +<p>Fields without initializers are initialized to <code>undefined</code>.</p> + +<pre class="brush: js">class ClassWithInstanceField { + instanceField +} + +const instance = new ClassWithInstanceField() +console.assert(instance.hasOwnProperty('instanceField')) +console.log(instance.instanceField) +// expected output: "undefined"</pre> + +<p>Like properties, field names may be computed.</p> + +<pre class="brush: js">const PREFIX = 'prefix' + +class ClassWithComputedFieldName { + [`${PREFIX}Field`] = 'prefixed field' +} + +const instance = new ClassWithComputedFieldName() +console.log(instance.prefixField) +// expected output: "prefixed field"</pre> + +<p>When initializing fields <code>this</code> refers to the class instance under construction. Just as in public instance methods, if you're in a subclass you can access the superclass prototype using <code>super</code>.</p> + +<pre class="brush: js">class ClassWithInstanceField { + baseInstanceField = 'base field' + anotherBaseInstanceField = this.baseInstanceField + baseInstanceMethod() { return 'base method output' } +} + +class SubClassWithInstanceField extends ClassWithInstanceField { + subInstanceField = super.baseInstanceMethod() +} + +const base = new ClassWithInstanceField() +const sub = new SubClassWithInstanceField() + +console.log(base.anotherBaseInstanceField) +// expected output: "base field" + +console.log(sub.subInstanceField) +// expected output: "base method output"</pre> + +<h2 id="Public_methods">Public methods</h2> + +<h3 id="Public_static_methods">Public static methods</h3> + +<p>The <code><strong>static</strong></code> keyword defines a static method for a class. Static methods aren't called on instances of the class. Instead, they're called on the class itself. These are often utility functions, such as functions to create or clone objects.</p> + +<p>{{EmbedInteractiveExample("pages/js/classes-static.html")}}</p> + +<div class="hidden"> +<p>The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p> +</div> + +<p>The static methods are added to the class constructor with {{jsxref("Global_Objects/Object/defineProperty", "Object.defineProperty()")}} at class evaluation time. These methods are writable, non-enumerable, and configurable.</p> + +<h3 id="Public_instance_methods">Public instance methods</h3> + +<p>As the name implies, public instance methods are methods available on class instances.</p> + +<pre class="brush: js">class ClassWithPublicInstanceMethod { + publicMethod() { + return 'hello world' + } +} + +const instance = new ClassWithPublicInstanceMethod() +console.log(instance.publicMethod()) +// expected output: "hello world"</pre> + +<p>Public instance methods are added to the class prototype at the time of class evaluation using {{jsxref("Global_Objects/Object/defineProperty", "Object.defineProperty()")}}. They are writable, non-enumerable, and configurable.</p> + +<p>You may make use of generator, async, and async generator functions.</p> + +<pre class="brush: js">class ClassWithFancyMethods { + *generatorMethod() { } + async asyncMethod() { } + async *asyncGeneratorMethod() { } +}</pre> + +<p>Inside instance methods, <code>this</code> refers to the instance itself. In subclasses, <code>super</code> lets you access the superclass prototype, allowing you to call methods from the superclass.</p> + +<pre class="brush: js">class BaseClass { + msg = 'hello world' + basePublicMethod() { + return this.msg + } +} + +class SubClass extends BaseClass { + subPublicMethod() { + return super.basePublicMethod() + } +} + +const instance = new SubClass() +console.log(instance.subPublicMethod()) +// expected output: "hello world" +</pre> + +<p>Getters and setters are special methods that bind to a class property and are called when that property is accessed or set. Use the <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get">get</a> and <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set">set</a> syntax to declare a public instance getter or setter.</p> + +<pre class="brush: js">class ClassWithGetSet { + #msg = 'hello world' + get msg() { + return this.#msg + } + set msg(x) { + this.#msg = `hello ${x}` + } +} + +const instance = new ClassWithGetSet() +console.log(instance.msg) +// expected output: "hello world" + +instance.msg = 'cake' +console.log(instance.msg) +// expected output: "hello cake" +</pre> + +<h2 id="Private_fields">Private fields</h2> + +<h3 id="Private_static_fields">Private static fields </h3> + +<p>Private fields are accessible on the class constructor from inside the class declaration itself.</p> + +<p>The limitation of static variables being called by only static methods still holds. </p> + +<pre class="brush: js">class ClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD + + static publicStaticMethod() { + ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42 + return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD + } +} + +assert(ClassWithPrivateStaticField.publicStaticMethod() === 42)</pre> + +<p>Private static fields are added to the class constructor at class evaluation time.</p> + +<p>There is a provenance restriction on private static fields. Only the class which defines the private static field can access the field.</p> + +<p>This can lead to unexpected behaviour when using <strong><code>this</code></strong>.</p> + +<pre class="brush: js">class BaseClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD + + static basePublicStaticMethod() { + this.#PRIVATE_STATIC_FIELD = 42 + return this.#PRIVATE_STATIC_FIELD + } +} + +class SubClass extends BaseClassWithPrivateStaticField { } + +assertThrows(() => SubClass.basePublicStaticMethod(), TypeError) +</pre> + +<h3 id="Private_instance_fields">Private instance fields</h3> + +<p>Private instance fields are declared with <strong># names </strong>(pronounced "<em>hash names</em>"), which are identifiers prefixed with <code>#</code>. The <code>#</code> is a part of the name itself. It is used for declaration and accessing as well.</p> + +<p>The encapsulation is enforced by the language. It is a syntax error to refer to <code>#</code> names from out of scope.</p> + +<pre class="brush: js">class ClassWithPrivateField { + #privateField + + constructor() { + this.#privateField = 42 + this.#randomField = 666 // Syntax error + } +} + +const instance = new ClassWithPrivateField() +instance.#privateField === 42 // Syntax error +</pre> + +<h2 id="Private_Methods">Private Methods</h2> + +<h3 id="Private_static_methods">Private static methods</h3> + +<p>Like their public equivalent, private static methods are called on the class itself, not instances of the class. Like private static fields, they are only accessible from inside the class declaration.</p> + +<p>Private static methods may be generator, async, and async generator functions.</p> + +<pre class="brush: js">class ClassWithPrivateStaticMethod { + static #privateStaticMethod() { + return 42 + } + + static publicStaticMethod1() { + return ClassWithPrivateStaticMethod.#privateStaticMethod(); + } + + static publicStaticMethod2() { + return this.#privateStaticMethod(); + } +} + +assert(ClassWithPrivateStaticField.publicStaticMethod1() === 42); +assert(ClassWithPrivateStaticField.publicStaticMethod2() === 42); +</pre> + +<p>This can lead to unexpected behaviour when using <strong><code>this</code></strong>(because <code>this</code> binding rule applies).</p> + +<pre class="brush: js">class Base { + static #privateStaticMethod() { + return 42; + } + static publicStaticMethod1() { + return Base.#privateStaticMethod(); + } + static publicStaticMethod2() { + return this.#privateStaticMethod(); + } +} + +class Derived extends Base {} + +console.log(Derived.publicStaticMethod1()); // 42 +console.log(Derived.publicStaticMethod2()); // TypeError +</pre> + +<h3 id="Private_instance_methods">Private instance methods</h3> + +<p>Private instance methods are methods available on class instances whose access is restricted in the same manner as private instance fields.</p> + +<pre class="brush: js">class ClassWithPrivateMethod { + #privateMethod() { + return 'hello world' + } + + getPrivateMessage() { + return this.#privateMethod() + } +} + +const instance = new ClassWithPrivateMethod() +console.log(instance.getPrivateMessage()) +// expected output: "hello world"</pre> + +<p>Private instance methods may be generator, async, or async generator functions. Private getters and setters are also possible:</p> + +<pre class="brush: js">class ClassWithPrivateAccessor { + #message + + get #decoratedMessage() { + return `✨${this.#message}✨` + } + set #decoratedMessage(msg) { + this.#message = msg + } + + constructor() { + this.#decoratedMessage = 'hello world' + console.log(this.#decoratedMessage) + } +} + +new ClassWithPrivateAccessor(); +// expected output: "✨hello world✨" +</pre> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td><a href="https://tc39.es/proposal-class-fields/#prod-FieldDefinition">FieldDefinition production</a></td> + <td>Stage 3</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + +<h3 id="Public_class_fields">Public class fields</h3> + + + +<p>{{Compat("javascript.classes.public_class_fields")}}</p> + +<h3 id="Private_class_fields">Private class fields</h3> + +<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div> + +<p>{{Compat("javascript.classes.private_class_fields")}}</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://rfrn.org/~shu/2018/05/02/the-semantics-of-all-js-class-elements.html">The Semantics of All JS Class Elements</a></li> +</ul> diff --git a/files/ko/web/javascript/reference/classes/constructor/index.html b/files/ko/web/javascript/reference/classes/constructor/index.html new file mode 100644 index 0000000000..f07dbd43b9 --- /dev/null +++ b/files/ko/web/javascript/reference/classes/constructor/index.html @@ -0,0 +1,128 @@ +--- +title: constructor +slug: Web/JavaScript/Reference/Classes/constructor +tags: + - Classes + - ECMAScript 2015 + - JavaScript + - Reference +translation_of: Web/JavaScript/Reference/Classes/constructor +--- +<div>{{jsSidebar("Classes")}}</div> + +<p><strong><code>constructor</code></strong> 메서드는 {{jsxref("Statements/class", "class")}} 내에서 객체를 생성하고 초기화하기 위한 특별한 메서드입니다.</p> + +<div>{{EmbedInteractiveExample("pages/js/classes-constructor.html")}}</div> + + + +<h2 id="구문">구문</h2> + +<pre class="syntaxbox">constructor([<em>arguments</em>]) { ... } +</pre> + +<h2 id="설명">설명</h2> + +<p>클래스는 <code>constructor</code>라는 이름을 가진 특별한 메서드를 하나씩만 가질 수 있습니다. 두 개 이상의 <code>constructor</code> 메서드는 {{jsxref("SyntaxError")}}를 유발합니다.</p> + +<p>생성자 메서드는 {{jsxref("Operators/super", "super")}} 키워드를 사용하여 상위 클래스의 생성자 메서드를 호출할 수 있습니다.</p> + +<p>생성자 메서드를 지정하지 않은 경우엔 기본 생성자 메서드를 사용합니다.</p> + +<h2 id="예제">예제</h2> + +<h3 id="constructor_메서드_사용하기"><code>constructor</code> 메서드 사용하기</h3> + +<pre class="brush: js">class Square extends Polygon { + constructor(length) { + // length로 다각형의 넓이와 높이를 정의하기 위해 부모클래스의 생성자를 호출합니다. + super(length, length); + // Note: 파생 클래스에서, 'this'를 사용하기 전에는 반드시 super()를 + // 호출하여야 합니다. 그렇지 않을 경우 참조에러가 발생합니다. + this.name = 'Square'; + } + + get area() { + return this.height * this.width; + } + + set area(value) { + this.area = value; + } +}</pre> + +<h3 id="다른예제">다른예제</h3> + +<pre class="brush: js">class Polygon { + constructor() { + this.name = "Polygon"; + } +} + +class Square extends Polygon { + constructor() { + super(); + } +} + +class Rectangle {} + +Object.setPrototypeOf(Square.prototype, Rectangle.prototype); + +console.log(Object.getPrototypeOf(Square.prototype) === Polygon.prototype); //false +console.log(Object.getPrototypeOf(Square.prototype) === Rectangle.prototype); //true + +let newInstance = new Square(); +console.log(newInstance.name); //Polygon</pre> + +<p>여기서 <strong>Square</strong> 클래스의 프로토 타입이 변경되었지만 사각형의 새 인스턴스가 만들어 질 때 이전 기본 클래스 인 <strong>Polygon</strong>의 생성자가 호출됩니다.</p> + +<h3 id="기본_생성자">기본 생성자</h3> + +<p>만약 생성자를 지정하지 않을 경우 기본 생성자 메서드를 사용합니다. 기본 클래스(즉, 아무것도 상속하지 않는 클래스)의 기본 생성자 메서드는 다음과 같습니다.</p> + +<pre class="brush: js">constructor() {} +</pre> + +<p>파생 클래스의 경우, 기본 생성자는 다음과 같습니다.</p> + +<pre class="brush: js">constructor(...args) { + super(...args); +}</pre> + +<h2 id="명세">명세</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">명세</th> + <th scope="col">상태</th> + <th scope="col">설명</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-static-semantics-constructormethod', 'Constructor Method')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-static-semantics-constructormethod', 'Constructor Method')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="브라우저_호환성">브라우저 호환성</h2> + + + +<p>{{Compat("javascript.classes.constructor")}}</p> + +<h2 id="같이_보기">같이 보기</h2> + +<ul> + <li>{{jsxref("Operators/super", "super")}}</li> + <li><a href="/ko/docs/Web/JavaScript/Reference/Operators/class"><code>class</code> 표현식</a></li> + <li><a href="/ko/docs/Web/JavaScript/Reference/Statements/class"><code>class</code> 선언문</a></li> + <li><a href="/ko/docs/Web/JavaScript/Reference/Classes">클래스</a></li> +</ul> diff --git a/files/ko/web/javascript/reference/classes/extends/index.html b/files/ko/web/javascript/reference/classes/extends/index.html new file mode 100644 index 0000000000..e1ae2eac31 --- /dev/null +++ b/files/ko/web/javascript/reference/classes/extends/index.html @@ -0,0 +1,112 @@ +--- +title: extends +slug: Web/JavaScript/Reference/Classes/extends +tags: + - Classes + - ECMAScript6 + - JavaScript +translation_of: Web/JavaScript/Reference/Classes/extends +--- +<div>{{jsSidebar("Classes")}}</div> + +<p><strong><code>extends</code></strong> 키워드는 클래스를 다른 클래스의 자식으로 만들기 위해 <a href="/ko/docs/Web/JavaScript/Reference/Statements/class" title="class declarations">class 선언</a> 또는 <a href="/ko/docs/Web/JavaScript/Reference/Operators/class" title="class expressions">class 식</a>에 사용됩니다.</p> + +<p>{{EmbedInteractiveExample("pages/js/classes-extends.html", "taller")}}</p> + +<div class="hidden"> +<p>The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p> +</div> + +<h2 id="구문">구문</h2> + +<pre class="syntaxbox">class ChildClass extends ParentClass { ... }</pre> + +<h2 id="설명">설명</h2> + +<p><code>extends</code> 키워드는 내장 객체뿐만 아니라 사용자 정의 클래스를 하위 클래스로 만들기 위해 사용될 수 있습니다.</p> + +<p>확장( 클래스)의 <code>.prototype</code>은 {{jsxref("Object")}} 또는 {{jsxref("null")}}이어야 합니다.</p> + +<h2 id="예">예</h2> + +<h3 id="extends_사용하기"><code>extends</code> 사용하기</h3> + +<p>첫 번째 예는 <code>Polygon</code> 클래스로부터 <code>Square</code> 클래스를 만듭니다. 이 예는 <a href="https://googlechrome.github.io/samples/classes-es6/index.html">live demo</a> <a href="https://github.com/GoogleChrome/samples/blob/gh-pages/classes-es6/index.html">(source)</a>에서 발췌했습니다.</p> + +<pre class="brush: js">class Square extends Polygon { + constructor(length) { + // 여기서, length와 함께 부모 클래스의 생성자를 호출 + // Polygon의 너비 및 높이가 제공됨 + super(length, length); + // 주의: 파생 클래스에서, super()가 먼저 호출되어야 'this'를 + // 사용할 수 있습니다. 이를 빼먹으면 참조 오류가 발생합니다. + this.name = 'Square'; + } + + get area() { + return this.height * this.width; + } + + set area(value) { + this.area = value; + } +}</pre> + +<h3 id="내장_객체에_extends_사용하기">내장 객체에 <code>extends</code> 사용하기</h3> + +<p>이 예제는 내장 객체 {{jsxref("Date")}}를 확장합니다. 이 예제는 <a href="https://googlechrome.github.io/samples/classes-es6/index.html">live demo</a> <a href="https://github.com/GoogleChrome/samples/blob/gh-pages/classes-es6/index.html">(source)</a>에서 발췌했습니다.</p> + +<pre class="brush: js">class myDate extends Date { + constructor() { + super(); + } + + getFormattedDate() { + var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; + return this.getDate() + "-" + months[this.getMonth()] + "-" + this.getFullYear(); + } +}</pre> + +<h3 id="null_확장"><code>null</code> 확장</h3> + +<p>{{jsxref("null")}}에서 확장은 prototype 객체가 {{jsxref("Object.prototype")}}으로부터 상속받지 않은 것을 제외하면 보통 클래스처럼 동작합니다.</p> + +<pre class="brush: js">class nullExtends extends null { + constructor() {} +} + +Object.getPrototypeOf(nullExtends); // Function.prototype +Object.getPrototypeOf(nullExtends.prototype) // null</pre> + +<h2 id="스펙">스펙</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">스펙</th> + <th scope="col">상태</th> + <th scope="col">설명</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-class-definitions', 'extends')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>초기 정의.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-class-definitions', 'extends')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="브라우저_호환성">브라우저 호환성</h2> + +<p>{{Compat("javascript.classes.extends")}}</p> + +<h2 id="참조">참조</h2> + +<ul> + <li><a href="/ko/docs/Web/JavaScript/Reference/Classes">Classes</a></li> + <li><a href="/ko/docs/Web/JavaScript/Reference/Operators/super">super</a></li> +</ul> diff --git a/files/ko/web/javascript/reference/classes/index.html b/files/ko/web/javascript/reference/classes/index.html new file mode 100644 index 0000000000..59f72f7652 --- /dev/null +++ b/files/ko/web/javascript/reference/classes/index.html @@ -0,0 +1,402 @@ +--- +title: Classes +slug: Web/JavaScript/Reference/Classes +translation_of: Web/JavaScript/Reference/Classes +--- +<div>{{JsSidebar("Classes")}}</div> + +<p>Class는 객체를 생성하기 위한 템플릿입니다. 클래스는 데이터와 이를 조작하는 코드를 하나로 추상화합니다. 자바스크립트에서 클래스는 프로토타입을 이용해서 만들어졌지만 ES5의 클래스 의미와는 다른 문법과 의미를 가집니다.</p> + +<h2 id="Class_정의">Class 정의</h2> + +<p>Class는 사실 "특별한 {{jsxref("Functions", "함수", "", "true")}}"입니다. 함수를 {{jsxref("Operators/function", "함수 표현식", "", "true")}}과 {{jsxref("Statements/function", "함수 선언", "", "true")}}으로 정의할 수 있듯이 class 문법도 {{jsxref("Operators/class", "class 표현식", "", "true")}} and {{jsxref("Statements/class", "class 선언", "", "true")}} 두 가지 방법을 제공합니다.</p> + +<h3 id="Class_선언">Class 선언</h3> + +<p>Class를 정의하는 한 가지 방법은 <strong>class 선언</strong>을 이용하는 것입니다. class를 선언하기 위해서는 클래스의 이름(여기서 "Rectangle")과 함께 <code>class</code> 키워드를 사용해야 합니다.</p> + +<pre class="brush: js notranslate">class Rectangle { + constructor(height, width) { + this.height = height; + this.width = width; + } +}</pre> + +<h4 id="Hoisting">Hoisting</h4> + +<p><strong>함수 선언</strong>과 <strong>클래스 선언</strong>의 중요한 차이점은 함수 선언의 경우 {{Glossary("Hoisting", "호이스팅")}}이 일어나지만, 클래스 선언은 그렇지 않다는 것입니다. 클래스를 사용하기 위해서는 클래스를 먼저 선언 해야 합니다. 그렇지 않으면, 다음 코드는 {{jsxref("ReferenceError")}}를 던질 것입니다. :</p> + +<pre class="brush: js example-bad notranslate">const p = new Rectangle(); // ReferenceError + +class Rectangle {} +</pre> + +<h3 id="Class_표현식">Class 표현식</h3> + +<p><strong>Class 표현식</strong>은 class를 정의하는 또 다른 방법입니다. Class 표현식은 이름을 가질 수도 있고, 갖지 않을 수도 있습니다. 이름을 가진 class 표현식의 이름은 클래스 body의 local scope에 한해 유효합니다. (하지만, 클래스의 (인스턴스 이름이 아닌) {{jsxref("Function.name", "name")}} 속성을 통해 찾을 수 있습니다).</p> + +<pre class="brush: js notranslate">// unnamed +let Rectangle = class { + constructor(height, width) { + this.height = height; + this.width = width; + } +}; +console.log(Rectangle.name); +// 출력: "Rectangle" + +// named +let Rectangle = class Rectangle2 { + constructor(height, width) { + this.height = height; + this.width = width; + } +}; +console.log(Rectangle.name); +// 출력: "Rectangle2" +</pre> + +<div class="note"> +<p><strong>참고:</strong> 클래스 <strong>표현식</strong>에는 {{anch ( "Class 선언")}} 섹션에 설명된 것과 동일한 호이스팅 제한이 적용됩니다.</p> +</div> + +<h2 id="Class_body_와_메서드_정의">Class body 와 메서드 정의</h2> + +<p>Class body는 중괄호 <code>{}</code> 로 묶여 있는 안쪽 부분입니다. 이곳은 여러분이 메서드나 constructor와 같은 class 멤버를 정의할 곳입니다.</p> + +<h3 id="Strict_mode">Strict mode</h3> + +<p>클래스의 본문(body)은 {{jsxref("Strict_mode", "strict mode", "", "true")}}에서 실행됩니다. 즉, 여기에 적힌 코드는 성능 향상을 위해 더 엄격한 문법이 적용됩니다. 그렇지 않으면, 조용히 오류가 발생할 수 있습니다. 특정 키워드는 미래의 ECMAScript 버전용으로 예약됩니다.</p> + +<h3 id="Constructor_생성자">Constructor (생성자)</h3> + +<p>{{jsxref("Classes/constructor", "constructor", "", "true")}} 메서드는 <code>class</code> 로 생성된 객체를 생성하고 초기화하기 위한 특수한 메서드입니다. "constructor" 라는 이름을 가진 특수한 메서드는 클래스 안에 한 개만 존재할 수 있습니다. 만약 클래스에 여러 개의 <code>constructor</code> 메서드가 존재하면 {{jsxref("SyntaxError")}} 가 발생할 것입니다.</p> + +<p>constructor는 부모 클래스의 constructor를 호출하기 위해 <code>super</code> 키워드를 사용할 수 있습니다.</p> + +<h3 id="프로토타입_메서드">프로토타입 메서드</h3> + +<p>{{jsxref("Functions/Method_definitions", "메서드 정의", "", "true")}}도 참조해보세요.</p> + +<pre class="brush: js notranslate">class Rectangle { + constructor(height, width) { + this.height = height; + this.width = width; + } + // Getter + get area() { + return this.calcArea(); + } + // 메서드 + calcArea() { + return this.height * this.width; + } +} + +const square = new Rectangle(10, 10); + +console.log(square.area); // 100</pre> + +<h3 id="정적_메서드와_속성">정적 메서드와 속성</h3> + +<p>{{jsxref("Classes/static", "static", "", "true")}} 키워드는 클래스를 위한 정적(static) 메서드를 정의합니다. 정적 메서드는 클래스의 인스턴스화(<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript#The_object_(class_instance)" title='An example of class instance is "var john = new Person();"'>instantiating</a>) 없이 호출되며, 클래스의 인스턴스에서는 호출할 수 없습니다. 정적 메서드는 어플리케이션(application)을 위한 유틸리티(utility) 함수를 생성하는 데 주로 사용됩니다. 반면, 정적 속성은 캐시, 고정 환경설정 또는 인스턴스 간에 복제할 필요가 없는 기타 데이터에 유용합니다.</p> + +<pre class="brush: js notranslate">class Point { + constructor(x, y) { + this.x = x; + this.y = y; + } + + static displayName = "Point"; + static distance(a, b) { + const dx = a.x - b.x; + const dy = a.y - b.y; + + return Math.hypot(dx, dy); + } +} + +const p1 = new Point(5, 5); +const p2 = new Point(10, 10); +p1.displayName; // undefined +p1.distance; // undefined +p2.displayName; // undefined +p2.distance; // undefined + +console.log(Point.displayName); // "Point" +console.log(Point.distance(p1, p2)); // 7.0710678118654755</pre> + +<h3 id="프로토타입_및_정적_메서드를_사용한_this_바인딩">프로토타입 및 정적 메서드를 사용한 <code>this</code> 바인딩</h3> + +<p>메서드를 변수에 할당 한 다음 호출하는 것과 같이, 정적 메서드나 프로토타입 메서드가 {{jsxref("Operators/this", "this")}} 값 없이 호출될 때, <code>this</code> 값은 메서드 안에서 <code>undefined</code>가 됩니다. 이 동작은 {{jsxref("Strict_mode", "\"use strict\"")}} 명령어 없이도 같은 방식으로 동작하는데, <code>class</code> 문법 안에 있는 코드는 항상 strict mode 로 실행되기 때문입니다.</p> + +<pre class="brush: js notranslate">class Animal { + speak() { + return this; + } + static eat() { + return this; + } +} + +let obj = new Animal(); +obj.speak(); // the Animal object +let speak = obj.speak; +speak(); // undefined + +Animal.eat() // class Animal +let eat = Animal.eat; +eat(); // undefined</pre> + +<p>위에 작성된 코드를 전통적 방식의 함수기반의 non–strict mode 구문으로 재작성하면, <code>this</code> 메서드 호출은 기본적으로 {{Glossary("Global_object", "전역 객체")}}인 초기 <code>this</code> 값에 자동으로 바인딩 됩니다. Strict mode에서는 자동 바인딩이 발생하지 않습니다; <code>this</code> 값은 전달된 대로 유지됩니다.</p> + +<pre class="brush: js notranslate">function Animal() { } + +Animal.prototype.speak = function() { + return this; +} + +Animal.eat = function() { + return this; +} + +let obj = new Animal(); +let speak = obj.speak; +speak(); // global object (in non–strict mode) + +let eat = Animal.eat; +eat(); // global object (in non-strict mode)</pre> + +<h3 id="인스턴스_속성">인스턴스 속성</h3> + +<p>인스턴스 속성은 반드시 클래스 메서드 내에 정의되어야 합니다:</p> + +<pre class="brush: js notranslate">class Rectangle { + constructor(height, width) { + this.height = height; + this.width = width; + } +}</pre> + +<p>정적 (클래스사이드) 속성과 프로토타입 데이터 속성은 반드시 클래스 선언부 바깥쪽에서 정의되어야 합니다. </p> + +<pre class="brush: js notranslate">Rectangle.staticWidth = 20; +Rectangle.prototype.prototypeWidth = 25; +</pre> + +<h3 id="Field_선언">Field 선언</h3> + +<div class="blockIndicator warning"> +<p>public과 private 필드 선언은 자바스크립트 표준화 위원회에 <a href="https://github.com/tc39/proposal-class-fields">실험적 기능 (stage 3)</a> <a href="https://tc39.es/">TC39</a> 로 제안되어있습니다. 현재 이를 지원하는 브라우져는 제한적인 상태입니다만, <a href="https://babeljs.io/">Babel</a> 과 같은 build 시스템을 사용한다면 이 기능을 사용해볼 수 있습니다.</p> +</div> + +<h4 id="Public_필드_선언">Public 필드 선언</h4> + +<p>자바스크립트의 필드 선언 문법을 사용해서 위의 예제는 아래와 같이 다시 쓰여질 수 있습니다.</p> + +<pre class="brush: js notranslate">class Rectangle { + height = 0; + width; + constructor(height, width) { + this.height = height; + this.width = width; + } +}</pre> + +<p>필드를 먼저 선언함으로서 클래스 정의는 self-documenting에 가까워졌고 필드는 언제나 존재하는 상태가 됩니다.</p> + +<p>위의 예에서 봤듯이 필드 선언은 기본 값과 같이 선언될 수도 있습니다.</p> + +<p>자세한 내용은 {{jsxref("Classes/Public_class_fields", "public class fields", "", "true")}}를 참조하세요.</p> + +<h4 id="Private_필드_선언">Private 필드 선언</h4> + +<p>private 필드를 사용하면 아래와 같이 예제를 개선할 수 있습니다.</p> + +<pre class="brush: js notranslate">class Rectangle { + #height = 0; + #width; + constructor(height, width) { + this.#height = height; + this.#width = width; + } +}</pre> + +<p>클래스의 바깥에서 private 필드를 접근하려고 하면 에러가 발생합니다. private필드는 클래스 내부에서만 읽고 쓰기가 가능합니다. 클래스 외부에서 보이지 않도록 정의하였으므로 클래스가 버젼업 되면서 내부 구현이 바뀌더라도 클래스 사용자 입장에서는 이에 아무런 영항을 받지 않도록 할 수 있습니다.</p> + +<div class="blockIndicator note"> +<p>Private 필드는 사용전에 선언되어야 합니다.</p> +</div> + +<p>일반적인 프로퍼티와는 다르게 private 필드는 값을 할당하면서 만들어질 수 없습니다.</p> + +<p>자세한 내용은 {{jsxref("Classes/Private_class_fields", "private class fields", "", "true")}}를 참조하세요.</p> + +<h2 id="extends를_통한_클래스_상속sub_classing"><code>extends</code>를 통한 클래스 상속(sub classing)</h2> + +<p>{{jsxref("Classes/extends", "extends")}} 키워드는 <em>클래스 선언</em>이나 <em>클래스 표현식</em>에서 다른 클래스의 자식 클래스를 생성하기 위해 사용됩니다.</p> + +<pre class="brush: js notranslate">class Animal { + constructor(name) { + this.name = name; + } + + speak() { + console.log(`${this.name} makes a noise.`); + } +} + +class Dog extends Animal { + constructor(name) { + super(name); // super class 생성자를 호출하여 name 매개변수 전달 + } + + speak() { + console.log(`${this.name} barks.`); + } +} + +let d = new Dog('Mitzie'); +d.speak(); // Mitzie barks.</pre> + +<p>subclass에 constructor가 있다면, "this"를 사용하기 전에 가장 먼저 super()를 호출해야 합니다.</p> + +<p>또한 es5에서 사용되던 전통적인 함수 기반의 클래스를 통하여 확장할 수도 있습니다.</p> + +<pre class="brush: js notranslate">function Animal (name) { + this.name = name; +} + +Animal.prototype.speak = function () { + console.log(`${this.name} makes a noise.`); +} + +class Dog extends Animal { + speak() { + console.log(`${this.name} barks.`); + } +} + +let d = new Dog('Mitzie'); +d.speak(); // Mitzie barks. + +// 유사한 메서드의 경우, 자식의 메서드가 부모의 메서드보다 우선합니다</pre> + +<p>클래스는 생성자가 없는 객체(non-constructible)을 확장할 수 없습니다. 만약 기존의 생성자가 없는 객체을 확장하고 싶다면, 이 메서드를 사용하세요. {{jsxref("Object.setPrototypeOf()")}}:</p> + +<pre class="brush: js notranslate">const Animal = { + speak() { + console.log(`${this.name} makes a noise.`); + } +}; + +class Dog { + constructor(name) { + this.name = name; + } +} + +// 이 작업을 수행하지 않으면 speak를 호출할 때 TypeError가 발생합니다 +Object.setPrototypeOf(Dog.prototype, Animal); + +let d = new Dog('Mitzie'); +d.speak(); // Mitzie makes a noise.</pre> + +<h2 id="Species">Species</h2> + +<p>배열을 상속 받은 MyArray 클래스에서 {{jsxref("Array")}} Object를 반환하고 싶을 수도 있을 것입니다. 그럴때 Species 패턴은 기본 생성자를 덮어쓰도록 해줍니다.</p> + +<p>예를 들어, {{jsxref("Array.map", "map()")}}과 같은 기본 생성자를 반환하는 메서드를 사용할 때 이 메서드가 MyArray 객체 대신 <code>Array</code> 객체가 반환하도록 하고 싶을 것입니다. {{jsxref("Symbol.species")}} 심볼은 이러한 것을 가능하게 해줍니다:</p> + +<pre class="brush: js notranslate">class MyArray extends Array { + // 부모 Array 생성자로 species 덮어쓰기 + static get [Symbol.species]() { return Array; } +} +var a = new MyArray(1,2,3); +var mapped = a.map(x => x * x); + +console.log(mapped instanceof MyArray); // false +console.log(mapped instanceof Array); // true</pre> + +<h2 id="super_를_통한_상위_클래스_호출"><code>super</code> 를 통한 상위 클래스 호출</h2> + +<p>{{jsxref("Operators/super", "super")}} 키워드는 객체의 부모가 가지고 있는 메서드를 호출하기 위해 사용됩니다. 이는 프로토타입 기반 상속보다 좋은 점 중 하나입니다.</p> + +<pre class="brush: js notranslate">class Cat { + constructor(name) { + this.name = name; + } + + speak() { + console.log(`${this.name} makes a noise.`); + } +} + +class Lion extends Cat { + speak() { + super.speak(); + console.log(`${this.name} roars.`); + } +} + +let l = new Lion('Fuzzy'); +l.speak(); +// Fuzzy makes a noise. +// Fuzzy roars.</pre> + +<h2 id="Mix-ins">Mix-ins</h2> + +<p>추상 서브 클래스 또는 믹스-인은 클래스를 위한 템플릿입니다. ECMAScript 클래스는 하나의 단일 슈퍼클래스만을 가질 수 있으며, 예를 들어 툴링 클래스로부터의 다중 상속은 불가능합니다. 기능은 반드시 슈퍼클래스에서 제공되어야 합니다.</p> + +<p>슈퍼클래스를 인자로 받고 이 슈퍼클래스를 확장하는 서브클래스를 생성하여 반환하는 함수를 사용하여 ECMAScript에서 믹스-인을 구현할 수 있습니다:</p> + +<pre class="brush: js notranslate">var calculatorMixin = Base => class extends Base { + calc() { } +}; + +var randomizerMixin = Base => class extends Base { + randomize() { } +};</pre> + +<p>위 믹스-인을 사용하는 클래스는 다음과 같이 작성할 수 있습니다:</p> + +<pre class="brush: js notranslate">class Foo { } +class Bar extends calculatorMixin(randomizerMixin(Foo)) { }</pre> + +<h2 id="클래스_재정의">클래스 재정의</h2> + +<p>클래스는 재정의될 수 없습니다. 재정의를 시도하면 <code>SyntaxError</code> 가 발생합니다.</p> + +<p>이를 실험해보고 싶으면 FireFox Web Console (<strong>Tools </strong>><strong> Web Developer </strong>><strong> Web Console</strong>) 에서 같은 이름으로 클래스를 두번 정의하려고 해보세요. 다음과 같은 오류를 보게 될 겁니다. <code>SyntaxError: redeclaration of let <em>ClassName</em>;</code>. (See further discussion of this issue in {{Bug(1428672)}}.) Doing something similar in Chrome Developer Tools gives you a message like <code>Uncaught SyntaxError: Identifier '<em>ClassName</em>' has already been declared at <anonymous>:1:1</code>.</p> + +<h2 id="명세서">명세서</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">명세서</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-class-definitions', 'Class definitions')}}</td> + </tr> + </tbody> +</table> + +<h2 id="브라우저_호환성">브라우저 호환성</h2> + + + +<p>{{Compat("javascript.classes")}}</p> + +<h2 id="참조">참조</h2> + +<ul> + <li>{{jsxref("Functions", "함수", "", "true")}}</li> + <li>{{jsxref("Statements/class", "class 선언", "", "true")}}</li> + <li>{{jsxref("Operators/class", "class 식", "", "true")}}</li> + <li>{{jsxref("Classes/Public_class_fields", "Public class fields", "", "true")}}</li> + <li>{{jsxref("Classes/Private_class_fields", "Private class fields", "", "true")}}</li> + <li>{{jsxref("Operators/super", "super")}}</li> + <li><a href="https://hacks.mozilla.org/2015/07/es6-in-depth-classes/">블로그 게시물: "ES6 In Depth: Classes"</a></li> + <li><a href="https://github.com/tc39/proposal-class-fields">Fields and public/private class properties proposal (stage 3)</a></li> +</ul> diff --git a/files/ko/web/javascript/reference/classes/private_class_fields/index.html b/files/ko/web/javascript/reference/classes/private_class_fields/index.html new file mode 100644 index 0000000000..ea5508ab27 --- /dev/null +++ b/files/ko/web/javascript/reference/classes/private_class_fields/index.html @@ -0,0 +1,201 @@ +--- +title: Private class fields +slug: Web/JavaScript/Reference/Classes/Private_class_fields +tags: + - Class + - JavaScript + - Private Field +translation_of: Web/JavaScript/Reference/Classes/Private_class_fields +--- +<div>{{JsSidebar("Classes")}}</div> + +<p>class 의 속성(property)들은 기본적으로 public 하며 class 외부에서 읽히고 수정될 수 있다. 하지만, ES2019 에서는 해쉬 <code>#</code> prefix 를 추가해 private class 필드를 선언할 수 있게 되었다.</p> + +<h2 id="Syntax">Syntax</h2> + +<pre class="notranslate">class ClassWithPrivateField { + #privateField +} + +class ClassWithPrivateMethod { + #privateMethod() { + return 'hello world' + } +} + +class ClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD +}</pre> + +<h2 id="Examples">Examples</h2> + +<h3 id="Private_static_fields">Private static fields</h3> + +<p>private 필드는 class 선언문 내부의 class 생성자(class constructor)에서 접근이 가능하다.</p> + +<p>static 메소드에서만 static 변수들을 호출할 수 있다는 제약은 그대로 유지된다.</p> + +<pre class="notranslate">class ClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD + + static publicStaticMethod() { + ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD = 42 + return ClassWithPrivateStaticField.#PRIVATE_STATIC_FIELD + } +} + +console.assert(ClassWithPrivateStaticField.publicStaticMethod() === 42)</pre> + +<p>Private static 필드는 class evaluation 시 class 생성자(class constructor)에 추가된다.</p> + +<p>Private static 필드는 해당 필드를 선언한 class 에서만 접근할 수 있다.</p> + +<p>이는 <code>this</code> 를 사용함에 있어 예상치 못한 동작을 야기할 수 있다.</p> + +<pre class="notranslate">class BaseClassWithPrivateStaticField { + static #PRIVATE_STATIC_FIELD + + static basePublicStaticMethod() { + this.#PRIVATE_STATIC_FIELD = 42 + return this.#PRIVATE_STATIC_FIELD + } +} + +class SubClass extends BaseClassWithPrivateStaticField { } + +let error = null + +try { + SubClass.basePublicStaticMethod() +} catch(e) { error = e} + +console.assert(error instanceof TypeError)</pre> + +<h3 id="Private_instance_fields">Private instance fields</h3> + +<p>private 인스턴스 필드는 <strong># 이름 ('해쉬 이름' 으로 발음)</strong>,<strong> </strong>즉 <code>#</code> prefix 를 가진 식별자로 선언된다. <code>#</code> 은 그 이름 자체의 일부이며 선언과 접근 시에 모두 사용된다.</p> + +<p>캡슐화(encapsulation) 는 언어로부터 강제된다(enforced by the language). 즉, scope 밖에서 <code>#</code> 이름에 접근하는 것은 syntax error 이다.</p> + +<pre class="notranslate">class ClassWithPrivateField { + #privateField + + constructor() { + this.#privateField = 42 + this.#randomField = 444 // Syntax error + } +} + +const instance = new ClassWithPrivateField() +instance.#privateField === 42 // Syntax error</pre> + +<h3 id="Private_Methods">Private Methods</h3> + +<h4 id="Private_static_methods">Private static methods</h4> + +<p><strong>private static 메소드</strong>는 public static 메소드처럼 인스턴스가 아닌 class 로부터 호출된다. 그리고 private static 필드처럼 class 선언문 내부에서만 접근 가능하다. </p> + +<p>private static 메소드는 generator, async 그리고 async generator 함수가 될 수 있다.</p> + +<pre class="notranslate">class ClassWithPrivateStaticMethod { + static #privateStaticMethod() { + return 42 + } + + static publicStaticMethod1() { + return ClassWithPrivateStaticMethod.#privateStaticMethod(); + } + + static publicStaticMethod2() { + return this.#privateStaticMethod(); + } +} + +console.assert(ClassWithPrivateStaticMethod.publicStaticMethod1() === 42); +console.assert(ClassWithPrivateStaticMethod.publicStaticMethod2() === 42);</pre> + +<p>이는 <code>this</code> 를 사용할 때 예상치 못한 동작을 발생시킬 수 있다. (이는 <code>this</code> binding rule 이 적용되기 때문이다.) 다음 예시에서 <code>Derived.publicStaticMethod2()</code> 를 호출할 때, <code>this</code> 는 class <code>Derived</code> (<code>Base</code> 가 아니라) 를 가리킨다. </p> + +<pre class="notranslate">class Base { + static #privateStaticMethod() { + return 42; + } + static publicStaticMethod1() { + return Base.#privateStaticMethod(); + } + static publicStaticMethod2() { + return this.#privateStaticMethod(); + } +} + +class Derived extends Base {} + +console.log(Derived.publicStaticMethod1()); // 42 +console.log(Derived.publicStaticMethod2()); // TypeError</pre> + +<h4 id="Private_instance_methods">Private instance methods</h4> + +<p>private 인스턴스 메소드는 private 인스턴스 필드와는 다르게 class 인스턴스로부터 접근 가능하다.</p> + +<pre class="notranslate">class ClassWithPrivateMethod { + #privateMethod() { + return 'hello world' + } + + getPrivateMessage() { + return this.#privateMethod() + } +} + +const instance = new ClassWithPrivateMethod() +console.log(instance.getPrivateMessage()) +// expected output: "hello world"</pre> + +<p>private 인스턴스 메소드는 generator, async 그리고 async generator 함수가 될 수 있다. private getter 와 setter 또한 가능하다:</p> + +<pre class="notranslate">class ClassWithPrivateAccessor { + #message + + get #decoratedMessage() { + return `✨${this.#message}✨` + } + set #decoratedMessage(msg) { + this.#message = msg + } + + constructor() { + this.#decoratedMessage = 'hello world' + console.log(this.#decoratedMessage) + } +} + +new ClassWithPrivateAccessor(); +// expected output: "✨hello world✨"</pre> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('Public and private instance fields', '#prod-FieldDefinition', 'FieldDefinition')}}</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + + + +<p>{{Compat("javascript.classes.private_class_fields")}}</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Classes/Public_class_fields">Public class fields</a></li> + <li><a href="https://rfrn.org/~shu/2018/05/02/the-semantics-of-all-js-class-elements.html">The Semantics of All JS Class Elements</a></li> +</ul> diff --git a/files/ko/web/javascript/reference/classes/static/index.html b/files/ko/web/javascript/reference/classes/static/index.html new file mode 100644 index 0000000000..02701e550d --- /dev/null +++ b/files/ko/web/javascript/reference/classes/static/index.html @@ -0,0 +1,136 @@ +--- +title: static +slug: Web/JavaScript/Reference/Classes/static +tags: + - Classes + - ECMAScript 2015 + - JavaScript + - 자바스크립트 + - 클래스 +translation_of: Web/JavaScript/Reference/Classes/static +--- +<div>{{jsSidebar("Classes")}}</div> + +<p><strong>static</strong> 키워드는 클래스의 정적 메서드를 정의합니다.</p> + +<p>{{EmbedInteractiveExample("pages/js/classes-static.html")}}</p> + +<div class="hidden"> +<p>The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p> +</div> + +<h2 id="문법">문법</h2> + +<pre class="syntaxbox">static methodName() { ... }</pre> + +<h2 id="설명">설명</h2> + +<p>정적 메서드는 클래스의 인스턴스 없이 호출이 가능하며 클래스가 인스턴스화되면 호출할 수 없다. 정적 메서드는 종종 어플리케이션의 유틸리티 함수를 만드는데 사용된다.</p> + +<h2 id="정적_메서드의_호출">정적 메서드의 호출</h2> + +<h4 id="다른_정적_메서드에서의_호출">다른 정적 메서드에서의 호출</h4> + +<p>동일한 클래스 내의 다른 정적 메서드 내에서 정적 메서드를 호출하는 경우 키워드 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code>를 사용할 수 있다.</p> + +<pre class="brush: js">class StaticMethodCall { + static staticMethod() { + return 'Static method has been called'; + } + static anotherStaticMethod() { + return this.staticMethod() + ' from another static method'; + } +} +StaticMethodCall.staticMethod(); +// 'Static method has been called' + +StaticMethodCall.anotherStaticMethod(); +// 'Static method has been called from another static method' +</pre> + +<h3 id="클래스_생성자_및_다른_메서드에서의_호출">클래스 생성자 및 다른 메서드에서의 호출</h3> + +<p>정적 메서드가 비정적 메서드에서 키워드<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this">this</a></code> 를 써서는 직접적인 접근을 할 수 없다. 바른 호출 방법은 클래스 명칭을 쓰거나, 즉 <code>CLASSNAME.STATIC_METHOD_NAME()</code> 을 이용하거나 혹은 그 메서드를 생성자의 한 속성으로 부르는 것으로, 즉 <code>constructor</code> : <code>this.constructor.STATIC_METHOD_NAME()</code>를 이용한다.</p> + +<pre class="brush: js">class StaticMethodCall { + constructor() { + console.log(StaticMethodCall.staticMethod()); + // 'static method has been called.' + + console.log(this.constructor.staticMethod()); + // 'static method has been called.' + } + + static staticMethod() { + return 'static method has been called.'; + } +} +</pre> + +<h2 id="예제">예제</h2> + +<p>아래 예제는 여러가지 내용을 설명합니다.</p> + +<ol> + <li>어떻게 정적 메서드가 클래스에서 구현되는지</li> + <li>클래스의 정적 맴버가 서브클래스화 되는 것을 보여줍니다.</li> + <li>정적 메서드가 어떤 경우에 호출 될 수 있는지와 없는지를 설명합니다.</li> +</ol> + +<pre class="brush: js">class Triple { + static triple(n) { + n = n || 1; //비트연산이 아니어야 합니다. + return n * 3; + } +} + +class BiggerTriple extends Triple { + static triple(n) { + return super.triple(n) * super.triple(n); + } +} + +console.log(Triple.triple()); // 3 +console.log(Triple.triple(6)); // 18 +console.log(BiggerTriple.triple(3)); // 81 +var tp = new Triple(); +console.log(BiggerTriple.triple(3)); // 81 (부모의 인스턴스에 영향을 받지 않습니다.) +console.log(tp.triple()); // 'tp.triple은 함수가 아닙니다.'. +console.log(tp.constructor.triple(4)); // 12 +</pre> + +<p> </p> + +<h2 id="명세서">명세서</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-class-definitions', 'Class definitions')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-class-definitions', 'Class definitions')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="브라우저_호환성">브라우저 호환성</h2> + +<p>{{Compat("javascript.classes.static")}}</p> + +<h2 id="참고">참고</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/class"><code>class</code> expression</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/class"><code>class</code> declaration</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Classes">Classes</a></li> +</ul> |