From 3900c8899b2111dc8ecced8365ddc591ff1ded26 Mon Sep 17 00:00:00 2001 From: 1101707 Date: Wed, 15 Mar 2023 01:21:54 +0900 Subject: [PATCH 01/38] =?UTF-8?q?ko=20:=20proposal-object-getownpropertyde?= =?UTF-8?q?scriptors=20=EB=B2=88=EC=97=AD=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oposal-object-getownpropertydescriptors.md | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/ko/proposal-object-getownpropertydescriptors.md diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md new file mode 100644 index 0000000..7ddf976 --- /dev/null +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -0,0 +1,147 @@ +# Object.getOwnPropertyDescriptors Proposal + +> [폴리필](https://www.npmjs.com/package/object.getownpropertydescriptors)은 해당 링크에 있습니다. + +## 제안한 사람 + +stage 0 단계에서 **[Rick Waldron](https://github.com/rwaldron)** 이 제안하였으나, 현재 공식적으로 제안한사람은 **[Jordan Harband](https://github.com/ljharb)** 입니다. + +## 적용 상태 + +해당 제안은 현재 [the TC39 process](https://github.com/tc39/ecma262/)의 stage 4 단계에 있습니다. + +해당 제안은 `Reflect.getOwnPropertyDescriptors`과 동일하나, 다른 버전과의 일관성을 위하여 `Object`의 public 정적 메서드로 구현되어있습니다. + +## 제안 동기 + +ECMAScript 에는 두 객체 간의 복사를 구현한 단일 메서드가 존재하지 않습니다. 복잡한 어플리케이션에 함수적 프로그래밍과 불변 객체의 필요성이 대두된 시점에서 모든 프레임워크, 라이브러리가 객체와 프로토 타입들 간의 복사를 자신만의 방식으로 각각 구현하고 있습니다. + +`Object.assign`으로 구현하게 되는 경우, 많은 혼란과 의도하지 않은 동작들이 발생하게 됩니다. 이는 복사가 단순히 **얕은 복사**이기 때문입니다. +(특히 복잡한 객체나 클래스의 프로토타입의 경우, descriptors나, 접근자를 삭제하는 방식이 아닌, 속성과 symbols에 직접 접근하는 복사 방식은 문제가 될 수 있다.) + +열거형의 여부를 떠나서 모든 descriptor를 확인하는 작업은 객체가 기본적으로 비열거형 메서드와 접근자를 가지고 있기 때문에 클래스와 클래스의 프로토타입의 구성을 구현하는데 중요합니다. + +또한 decorator의 경우, 다른 클래스와 믹스인의 descriptor들을 통해 확인할 수 있고 `Object.defineProperties`를 통해 쉽게 할당이 가능하다. 필요하지 않은 descriptor를 필터링하는 것은 반복적이지 않고 간단하다. + +마지막으로, 무엇보다도 두 객체간의 얕은 복사는 `Object.assign`와 거의 차이가 존재하지 않는다. + +## FAQs + +### `Reflect.getOwnPropertyDescriptors`이 꼭 있어야하나? + +이 제안의 목적이 여러 형태의 보일러플레이트를 단순화하고, 여러개의 방법들을 일치시키기 위함이므로 현재 `Reflect.getOwnPropertyDescriptors`의 또 다른 버전으로 생각할 수 있다. + +업데이트 : 위원회는 `Reflect`가 `Proxy`의 트랩을 미러링을 위한 것이므로 옵션이 아니라는 것을 사전에 결정하였습니다. + + +## 제안 로직 + +`Object.getOwnPropertyDescriptor`의 또 다른 버전으로서, 해당 제안은 제네릭 객체이 가진 모든 `descriptor`를 한번의 작업으로 탐색하는 것을 말한다. + +해당 제안의 **polyfill**은 아래와 같다. + +```javascript +if (!Object.hasOwnProperty('getOwnPropertyDescriptors')) { + Object.defineProperty( + Object, + 'getOwnPropertyDescriptors', + { + configurable: true, + writable: true, + value: function getOwnPropertyDescriptors(object) { + return Reflect.ownKeys(object).reduce((descriptors, key) => { + return Object.defineProperty( + descriptors, + key, + { + configurable: true, + enumerable: true, + writable: true, + value: Object.getOwnPropertyDescriptor(object, key) + } + ); + }, {}); + } + } + ); +} +``` + +## 설명하기 위한 예제 + +위의 폴리필은 ES5 또는 부분적인 ES2015를 지원하는 엔진에서 동작하는 보일러플레이트를 개선한 것이다. + +`Object.getOwnPropertyDescriptors`을 통해서 두개의 객체간 얕은 복사와 클로닝이 가능하다. 예제를 보자. + +```javascript +const shallowClone = (object) => Object.create( + Object.getPrototypeOf(object), + Object.getOwnPropertyDescriptors(object) +); + +const shallowMerge = (target, source) => Object.defineProperties( + target, + Object.getOwnPropertyDescriptors(source) +); +``` + +mixin를 통한 객체 또한 이 제안을 통해 개선이 가능하다. + +```javascript +let mix = (object) => ({ + with: (...mixins) => mixins.reduce( + (c, mixin) => Object.create( + c, Object.getOwnPropertyDescriptors(mixin) + ), object) +}); + +// multiple mixins example +let a = {a: 'a'}; +let b = {b: 'b'}; +let c = {c: 'c'}; +let d = mix(c).with(a, b); +``` + +만약 side effect를 피하고 setter/getter를 복사하며 구분 요소로 열거 가능한 속성을 사용하고자 `[[Set]]`/`[[Get]]` 대신 `[[DefineOwnProperty]]`/`[[GetOwnProperty]]`를 사용하는 방식을 `Object.assign`을 사용하여 구현하는 것을 생각해보자. + +제안 이전에 메서드는 아래와 같이 구현될 것이다. + +```javascript +function completeAssign(target, ...sources) { + sources.forEach(source => { + // grab keys descriptors + let descriptors = Object.keys(source).reduce((descriptors, key) => { + descriptors[key] = Object.getOwnPropertyDescriptor(source, key); + return descriptors; + }, {}); + // by default, Object.assign copies enumerable Symbols too + // so grab and filter Symbols as well + Object.getOwnPropertySymbols(source).forEach(sym => { + let descriptor = Object.getOwnPropertyDescriptor(source, sym); + if (descriptor.enumerable) { + descriptors[sym] = descriptor; + } + }); + Object.defineProperties(target, descriptors); + }); + return target; +} +``` + +그러나 `Object.getOwnPropertyDescriptors`를 사용하게 되면, 위의 보일러 플레이트가 아래와 같이 구현 가능하게 된다. + +```javascript +var completeAssign = (target, ...sources) => + sources.reduce((target, source) => { + let descriptors = Object.getOwnPropertyDescriptors(source); + Reflect.ownKeys(descriptors).forEach(key => { + if (!descriptors[key].enumerable) { + delete descriptors[key]; + } + }); + return Object.defineProperties(target, descriptors); + }, target); +``` + + + From 2ccb500059b54c3165b5d7b5b19755021d4171c3 Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Thu, 16 Mar 2023 01:39:50 +0900 Subject: [PATCH 02/38] =?UTF-8?q?summary=20:=20proposal-object-getownprope?= =?UTF-8?q?rtydescriptors=20=EC=9A=94=EC=95=BD=201=EC=B0=A8=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oposal-object-getownpropertydescriptors.md | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/summary/proposal-object-getownpropertydescriptors.md diff --git a/src/summary/proposal-object-getownpropertydescriptors.md b/src/summary/proposal-object-getownpropertydescriptors.md new file mode 100644 index 0000000..bd4f48a --- /dev/null +++ b/src/summary/proposal-object-getownpropertydescriptors.md @@ -0,0 +1,156 @@ +#PR + +## typo: fix mixin solution + +기존의 mixin에 대한 예제를 아래와 같이 사용하는 것이 더 나은 방법이라고 생각한다. + +```javascript +/** mixin solution */ +const mix = obj => ({ + with : (...mixins) => mixins.reduce((c, mixin) => shallowMerge(c, mixin), obj), +}); +``` + +### 기존의 제안 +```javascript +let mix = (object) => ({ + with: (...mixins) => mixins.reduce( + (c, mixin) => Object.create( + c, Object.getOwnPropertyDescriptors(mixin) + ), object) +}); +``` + +### PR의 제안 +```javascript +let mix = (object) => ({ + with: (...mixins) => mixins.reduce( + (c, mixin) => Object.defineProperties( + c, Object.getOwnPropertyDescriptors(mixin) + ), object) +}); +``` + +기존의 `Object.create()`대신 `Object.defineProperties()`를 사용한 것이다. 일단 두가지의 차이부터 알아야한다. + +### `Object.create()` + +> `Object.create()` 메서드는 지정된 프로토타입 객체 및 속성(property)을 갖는 새 객체를 만든다. + +```javascript +Object.create(proto[, propertiesObject]) +``` + +#### `proto` + +- 생성되는 객체가 가질 프로토타입 객체 +- `new` 연산자를 사용하여 생성하면, 기본적으로는 생성자 함수의 prototype 속성의 Object를 바인딩한다. + +#### `propertiesObject` + +- 프로토타입이 아닌 생성되는 객체가 가질 속성을 가진 객체 +- 속성명 : 속성 설명자를 각각 key, value로 가진 객체를 전달한다. +- `Object.defineProperties()`의 두번째 인수에 해당한다. 즉, 해당 함수를 두번째 인수로 넣어 수행하여 객체 내부에 속성을 정의한다. + +#### 고전적인 상속방법 + +```javascript +// Shape - 상위클래스 +function Shape() { + this.x = 0; + this.y = 0; +} + +// Rectangle - 하위클래스 +function Rectangle() { + Shape.call(this); // super 생성자 호출. +} + +// 하위클래스는 상위클래스를 확장 +Rectangle.prototype = Object.create(Shape.prototype); +Rectangle.prototype.constructor = Rectangle; +``` + +- super 생성자 호출 후, `Shape`의 프로토타입 객체를 `Rectangle`의 인스턴스도 사용하기 위해서 `prototype` 속성을 바인딩해야한다. +- `Rectangle.prototype = Shape.prototype`으로 할당을 하게 되면, `Rectangle`의 프로토타입 객체를 변경하게 되면 `Shape`의 인스턴스에게도 영향을 준다. +- 이를 위해 `Shape` 프로토타입 객체를 프로토타입으로 가지는 빈 객체를 생성(`Object.create()`), 해당 객체를 `Rectangle`의 `prototype` 속성으로 바인딩한다. +- `Object.create()`로 생성되는 객체는 `constructor`가 존재하지 않으므로 바인딩 해준다. + + +#### `propertiesObject` 인자 사용하기 + +```javascript +var o = Object.create(Object.prototype, { + foo: { writable: true, configurable: true, value: 'hello' }, + bar: { + configurable: false, + get: function() { return 10; }, + set: function(value) { console.log('Setting `o.bar` to', value); } + } +}); + +``` +- `Object.create()`에서 두번째 인자를 사용하였다. 생성되는 객체는 `foo`, `bar` 두개의 속성을 가진다. +- `foo`는 정규 '값 속성'으로, 기본으로 writable, enumerable 또는 configurable 속성은 `false` 이기 때문에 `{ value : 'hello'}`으로 선언할 수 있다. +- `bar`는 '접근자(accessor, getter-및-setter) 속성'으로 선언되어있다. + +'값 속성' 또는 '접근자 속성'과 같이 속성을 선언할 때 사용되는 객체를 **'속성 설명자'**라고 한다. + + +### `Object.defineProperties()` + +> 인자로 전달된 객체에 속성의 정의하거나 수정하여 객체를 반환한다. + +```javascript +Object.defineProperties(obj, props); +``` + +#### obj +- 속성을 정의하거나 수정할 객체 + +#### props +- `Object.create()`의 두번째 인자인 `propertiesObject`와 동일하다. +- 즉, 속성명과 해당 속성의 설명자(`descriptor`)를 말한다. 로직은 위의 `propertiesObject`과 차이가 없다. + + +### `Object.create(c, Object.getOwnPropertyDescriptors(mixin))`와 `Object.defineProperties(c, Object.getOwnPropertyDescriptors(mixin))`의 차이 + +- `Object.create()`는 `c`객체를 `prototype` 객체로 사용하는 빈 객체를 선언, 해당 객체에 속성의 설명자를 통해 속성을 할당한다. +- `Object.defineProperties()`는 `c`객체에 직접적으로 속성의 설명자를 통해 속성을 할당한다. + +즉, `prototype chain`상 빈 객체를 'bridge'를 두어 속성을 선언할 것인가, 객체에 직접 속성을 선언할 것인가의 차이로 볼 수 있다. 실제로 PR의 제안이 더 나은 방법인가에 대해서는 잘 모르겠다. 이를 결정하기 위해서 `mixin`에 대한 지식이 필요할 것으로 보인다. + + + +## Summary + +어쨌든 이를 통해 `Object.getOwnPropertyDescriptors()`의 의미는 해당 객체가 가지는 속성 설명자를 반환하기 위해 사용된다는 것을 알게 되었다. 아래에 제시하는 개념들에 대한 공부가 더 필요할 것으로 보인다. + +--- + +### mixin + +```javascript +let mix = (object) => ({ + with: (...mixins) => mixins.reduce( + (c, mixin) => Object.create( + c, Object.getOwnPropertyDescriptors(mixin) + ), object) +}); +``` + +### `Reflect` + +`Reflect`를 선언하는 코드는 아래와 같다. + +```javascript + global.Reflect = { + defineProperty: Object.defineProperty, + getOwnPropertyDescriptor: Object.getOwnPropertyDescriptor, + ownKeys: function ownKeys(genericObject) { + let gOPS = Object.getOwnPropertySymbols || function () { return []; }; + return Object.getOwnPropertyNames(genericObject) + .concat(gOPS(genericObject)); + } + }; +``` From 85c49b7669931fe2065d44dd50e336eed7de82cd Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Sat, 18 Mar 2023 19:19:12 +0900 Subject: [PATCH 03/38] =?UTF-8?q?summary=20:=20proposal-object-getownprope?= =?UTF-8?q?rtydescriptors=20proto=20=EA=B4=80=EB=A0=A8=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oposal-object-getownpropertydescriptors.md | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/summary/proposal-object-getownpropertydescriptors.md b/src/summary/proposal-object-getownpropertydescriptors.md index bd4f48a..69fc058 100644 --- a/src/summary/proposal-object-getownpropertydescriptors.md +++ b/src/summary/proposal-object-getownpropertydescriptors.md @@ -44,7 +44,28 @@ Object.create(proto[, propertiesObject]) #### `proto` - 생성되는 객체가 가질 프로토타입 객체 -- `new` 연산자를 사용하여 생성하면, 기본적으로는 생성자 함수의 prototype 속성의 Object를 바인딩한다. +- `new` 연산자를 사용하여 생성하면, 기본적으로는 생성자 함수의 `prototype` 속성의 Object를 바인딩한다. + +Prototype Object는 `__proto__` 속성을 가지는데 아래는 해당 속성의 폴리필이다. + +```javascript +Object.defineProperty( Object.prototype, "__proto__", { + get: function() { + return Object.getPrototypeOf( this ); + }, + set: function(o) { + // setPrototypeOf(..) as of ES6 + Object.setPrototypeOf( this, o ); + return o; + } +} ); +``` + +- Object.prototype 객체에 `__proto__` 속성을 선언한다. +- `defineProperty`는 세번째 인자로 해당 속성의 descriptor를 받는다. +- 실제로 해당 속성은 `Object.getPrototypeOf()`, `Object.setPrototypeOf`를 사용하여 해당 객체(`this`)의 prototype 객체를 반환한다. +- 즉, 기존에 존재하는 prototype 메서드를 쉽게 사용하기 위해서 속성으로 선언한 것으로 볼 수 있다. + #### `propertiesObject` From 8ee2e0f3e8f63c0345c63416a389bd7f0c17a08b Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Sat, 18 Mar 2023 19:19:25 +0900 Subject: [PATCH 04/38] =?UTF-8?q?summary=20:=20proposal-object-getownprope?= =?UTF-8?q?rtydescriptors=20appendix=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ject-getownpropertydescriptors-appendix.md | 247 ++++++++++++++++++ 1 file changed, 247 insertions(+) create mode 100644 src/summary/proposal-object-getownpropertydescriptors-appendix.md diff --git a/src/summary/proposal-object-getownpropertydescriptors-appendix.md b/src/summary/proposal-object-getownpropertydescriptors-appendix.md new file mode 100644 index 0000000..671243f --- /dev/null +++ b/src/summary/proposal-object-getownpropertydescriptors-appendix.md @@ -0,0 +1,247 @@ +# Object에 속성을 선언하는 방법. + +## 'property accessor', 속성의 접근자 + +> 속성 접근자는 `.`(dot) 또는 `[]`(square bracket)을 사용하여 객체에 접근하는 방법이다. + +- 이 접근자를 통해 역으로, 객체의 속성을 정의할 수 있다. +- 속성 접근자는 `string`, `symbol`만 사용할 수 있다. 이는 값만으로 구별가능해야하기 때문이다. + + +## `Object.defineProperty()`와 'descriptor', 속성의 설명자 + +JS는 객체에 속성을 선언하는 메서드를 `Object.defineProperty()`로 따로 만들어두었다. 이는 'descriptor'를 통해 속성을 정의하기 위함이다. + +```javascript +Object.defineProperty(obj, prop, descriptor) +``` + +### prop + +- 속성의 접근자의 역할을 할 key 값 (`string` or `symbol`) + + +### descriptor (설명자) + +기본적으로 할당을 통해 속성을 선언/수정하게 되면, 해당 속성에 대해 열거, 변경, 삭제가 가능하다. 하지만 해당 메서드를 사용하여 속성을 선언하게 되면 값 뿐 만 아니라 속성의 특성까지 정의할 수 있다. 기본적으로 메서드를 사용하여 선언된 속성은 열거, 수정, 삭제가 불가능하다. +추가적으로 해당 메서드는 할당을 통해 속성을 선언할 때 사용하는 `[[set]]`을 사용하는 것이 아니라, `[[DefineOwnProperty]]`를 사용한다. 즉 내부 로직이 다르기 때문에 속성의 세부적인 특성까지 선언할 수 있는 것이다. + +> 참고로, 객체에 내에 선언되는 속성을 `own property`라고 한다. 이는 객체의 속성이라도 프로토타입 체인에 의해 선언되는 속성이 존재하기 때문에 이를 구별하기 위해 `property`가 아닌 `own property`를 사용하는 것으로 보인다. + +> `enumerable`(열거가능)의 의미는 `for in`, `Object.keys`를 통해 속성을 열거하는 작업을 수행할 때 접근가능한 속성을 의미한다. + +이 때, descriptor는 `value descriptor`, `accessor descriptor` 두 가지를 통해 표현된다. 둘 모두 속성을 설명하는 특성을 객체의 형태로 표현하고 있는데, 두 개의 차이는 다음과 같다. + +1. `value descriptor` - 특정한 값을 가진 속성을 선언하는 방식, 객체 내의 `value` key로 **속성의 값**을 정의한다. +2. `acccessor descriptor` - `getter` `setter`를 선언하는 방식, `get`, `set` key로 **속성을 접근하는 방식**을 정의한다. + +### descriptor가 속성 + +속성(`own property`)을 선언하기 위해 사용하는 descriptor가 가진 속성(`descriptor property`)을 말한다. + +1. `configurable` - 속성의 descriptor의 변경여부. `false`을 경우, descriptor가 변경되지 않으며 해당 속성이 삭제되지 않는다. 하지만 `writable`이 `true`일 경우, 속성의 값은 변경될 수 있으며, `writable` 또한 `false`로 변경이 가능하다. +2. `enumerable` - 객체의 속성을 열거할 때, 속성 접근 가능여부 +3. `writable`- 객체의 값의 변경 가능여부 +4. `get` - 속성에 대한 접근 로직, `this` - 객체 +5. `set` - 속성의 값 할당 로직, `this` - 객체, parameter는 전달되는 값 + +어려운 점은, descriptor 또한 객체이므로 prototype link가 존재하여 prototype chain 상에서 접근가능한 속성(`descriptor property`) 또한 고려될 수 있다는 것이다. 이를 통해 descriptor의 prototype link 상의 prototype object를 변경하는 방식으로 여러 객체의 속성의 descriptor를 변경할 수 있게 된다. + +> **prototype chain의 객체가 가진 descritor 또한 객체의 속성에 영향을 준다.** + +```javascript +function MyClass() {} + +MyClass.prototype.x = 1; +Object.defineProperty(MyClass.prototype, "y", { + writable: false, + value: 1, +}); + +const a = new MyClass(); +a.x = 2; +console.log(a.x); // 2 +console.log(MyClass.prototype.x); // 1 +a.y = 2; // Ignored, throws in strict mode +console.log(a.y); // 1 +console.log(MyClass.prototype.y); // 1 +``` + +- `MyClass`의 prototype object에 `y` 속성을 `descriptor`를 사용하여 선언하였다. +- prototype object가 가진 속성이지만 `MyClass`의 모든 인스턴스에 해당 속성을 상속할 뿐 만 아니라, descriptor의 영향을 받는다. 이로 인해 모든 인스턴스는 `y` 속성에 대한 재선언 및 수정/삭제가 불가능하다. + +그렇다면, descriptor 또한 하나의 객체이므로 descriptor의 prototype chain 상의 속성이 객체의 속성`own property`에 영향을 줄 것인가에 대해서 생각해보자. +descriptor를 인자로 전달할 때, 접근 가능한 속성을 참조하여 snapshot으로 전달한다. 그러므로 descriptor의 prototype chain 상의 값을 변경하게 되더라도 `own property`에 전혀 영향을 주지 않는다. + +```javascript +var po = { writable: true }; + +var o = Object.create(po); +o.value = 3; + +var j = {}; +Object.defineProperty(j, 'y', o); +console.log(j.y); // 3 + +j.y = 4; +console.log(j.y); // 4 + +po.writable = false; +j.y = 5; +console.log(j.y); // 5 +``` + +- `o`는 `j`객체의 `y`속성 descriptor의 역할을 수행한다. `o`의 prototype link가 참조하는 prototype object인 `po`의 `writable`을 변경하여 속성값의 변경을 막고자 하였다. +- 하지만 `y` 속성의 수정이 이루어지는 것으로 보아, descriptor의 prototype object가 변경되더라도 영향을 주지 않는다. 즉, `defineProperty`호출 시점의 객체의 값을 사용한다. (deep copy의 방식) + +#### 결론적으로, descriptor의 prototype chain은 속성(`own property`)에 영향을 주지 않는다. 이는 호출시점에 descriptor의 값을 사용하기 때문이다. + +#### 객체의 prototype link로 참조하고 있는 prototype object에 descriptor로 선언된 속성은 속성(`own property`)에 영향을 준다. + +---- + + + +# Object를 복사하는 방법# Object에 속성을 선언하는 방법. + +## 'property accessor', 속성의 접근자 + +> 속성 접근자는 `.`(dot) 또는 `[]`(square bracket)을 사용하여 객체에 접근하는 방법이다. + +- 이 접근자를 통해 역으로, 객체의 속성을 정의할 수 있다. +- 속성 접근자는 `string`, `symbol`만 사용할 수 있다. 이는 값만으로 구별가능해야하기 때문이다. + + +## `Object.defineProperty()`와 'descriptor', 속성의 설명자 + +JS는 객체에 속성을 선언하는 메서드를 `Object.defineProperty()`로 따로 만들어두었다. 이는 'descriptor'를 통해 속성을 정의하기 위함이다. + +```javascript +Object.defineProperty(obj, prop, descriptor) +``` + +### prop + +- 속성의 접근자의 역할을 할 key 값 (`string` or `symbol`) + + +### descriptor (설명자) + +기본적으로 할당을 통해 속성을 선언/수정하게 되면, 해당 속성에 대해 열거, 변경, 삭제가 가능하다. 하지만 해당 메서드를 사용하여 속성을 선언하게 되면 값 뿐 만 아니라 속성의 특성까지 정의할 수 있다. 기본적으로 메서드를 사용하여 선언된 속성은 열거, 수정, 삭제가 불가능하다. +추가적으로 해당 메서드는 할당을 통해 속성을 선언할 때 사용하는 `[[set]]`을 사용하는 것이 아니라, `[[DefineOwnProperty]]`를 사용한다. 즉 내부 로직이 다르기 때문에 속성의 세부적인 특성까지 선언할 수 있는 것이다. + +> 참고로, 객체에 내에 선언되는 속성을 `own property`라고 한다. 이는 객체의 속성이라도 프로토타입 체인에 의해 선언되는 속성이 존재하기 때문에 이를 구별하기 위해 `property`가 아닌 `own property`를 사용하는 것으로 보인다. + +> `enumerable`(열거가능)의 의미는 `for in`, `Object.keys`를 통해 속성을 열거하는 작업을 수행할 때 접근가능한 속성을 의미한다. + +이 때, descriptor는 `value descriptor`, `accessor descriptor` 두 가지를 통해 표현된다. 둘 모두 속성을 설명하는 특성을 객체의 형태로 표현하고 있는데, 두 개의 차이는 다음과 같다. + +1. `value descriptor` - 특정한 값을 가진 속성을 선언하는 방식, 객체 내의 `value` key로 **속성의 값**을 정의한다. +2. `acccessor descriptor` - `getter` `setter`를 선언하는 방식, `get`, `set` key로 **속성을 접근하는 방식**을 정의한다. + +### descriptor가 속성 + +속성(`own property`)을 선언하기 위해 사용하는 descriptor가 가진 속성(`descriptor property`)을 말한다. + +1. `configurable` - 속성의 descriptor의 변경여부. `false`을 경우, descriptor가 변경되지 않으며 해당 속성이 삭제되지 않는다. 하지만 `writable`이 `true`일 경우, 속성의 값은 변경될 수 있으며, `writable` 또한 `false`로 변경이 가능하다. +2. `enumerable` - 객체의 속성을 열거할 때, 속성 접근 가능여부 +3. `writable`- 객체의 값의 변경 가능여부 +4. `get` - 속성에 대한 접근 로직, `this` - 객체 +5. `set` - 속성의 값 할당 로직, `this` - 객체, parameter는 전달되는 값 + +어려운 점은, descriptor 또한 객체이므로 prototype link가 존재하여 prototype chain 상에서 접근가능한 속성(`descriptor property`) 또한 고려될 수 있다는 것이다. 이를 통해 descriptor의 prototype link 상의 prototype object를 변경하는 방식으로 여러 객체의 속성의 descriptor를 변경할 수 있게 된다. + +> **prototype chain의 객체가 가진 descritor 또한 객체의 속성에 영향을 준다.** + +```javascript +function MyClass() {} + +MyClass.prototype.x = 1; +Object.defineProperty(MyClass.prototype, "y", { + writable: false, + value: 1, +}); + +const a = new MyClass(); +a.x = 2; +console.log(a.x); // 2 +console.log(MyClass.prototype.x); // 1 +a.y = 2; // Ignored, throws in strict mode +console.log(a.y); // 1 +console.log(MyClass.prototype.y); // 1 +``` + +- `MyClass`의 prototype object에 `y` 속성을 `descriptor`를 사용하여 선언하였다. +- prototype object가 가진 속성이지만 `MyClass`의 모든 인스턴스에 해당 속성을 상속할 뿐 만 아니라, descriptor의 영향을 받는다. 이로 인해 모든 인스턴스는 `y` 속성에 대한 재선언 및 수정/삭제가 불가능하다. + +그렇다면, descriptor 또한 하나의 객체이므로 descriptor의 prototype chain 상의 속성이 객체의 속성`own property`에 영향을 줄 것인가에 대해서 생각해보자. +descriptor를 인자로 전달할 때, 접근 가능한 속성을 참조하여 snapshot으로 전달한다. 그러므로 descriptor의 prototype chain 상의 값을 변경하게 되더라도 `own property`에 전혀 영향을 주지 않는다. + +```javascript +var po = { writable: true }; + +var o = Object.create(po); +o.value = 3; + +var j = {}; +Object.defineProperty(j, 'y', o); +console.log(j.y); // 3 + +j.y = 4; +console.log(j.y); // 4 + +po.writable = false; +j.y = 5; +console.log(j.y); // 5 +``` + +- `o`는 `j`객체의 `y`속성 descriptor의 역할을 수행한다. `o`의 prototype link가 참조하는 prototype object인 `po`의 `writable`을 변경하여 속성값의 변경을 막고자 하였다. +- 하지만 `y` 속성의 수정이 이루어지는 것으로 보아, descriptor의 prototype object가 변경되더라도 영향을 주지 않는다. 즉, `defineProperty`호출 시점의 객체의 값을 사용한다. (deep copy의 방식) + +#### 결론적으로, descriptor의 prototype chain은 속성(`own property`)에 영향을 주지 않는다. 이는 호출시점에 descriptor의 값을 사용하기 때문이다. + +#### 객체의 prototype link로 참조하고 있는 prototype object에 descriptor로 선언된 속성은 속성(`own property`)에 영향을 준다. + +[defineProperty MDN 공식 페이지](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) + +---- + +# Object를 복사하는 방법 + +## 얕은 복사(shallow copy)과 깊은 복사(deep copy) + +얕은 복사와 깊은 복사의 차이는, **원본의 변경이 사본에 영향을 주는가**의 차이이다. +1. shallow copy - 객체가 참조하는 값을 복사한다. JS는 기본적으로 객체의 속성이 해당 값을 참조하는 것이 아니라, 값이 저장된 주솟값을 참조하고 있기 때문에 해당 복사 방법을 사용한다. +2. deep copy - 객체가 참조하는 값의 주소값까지 복사한다. + +추가적으로, +1. call by reference - 전달되는 값을 주소값으로 사용하여, 해당 주소값이 참조하고 있는 값을 사용한다. +2. call by value - 전달되는 값을 그대로 값으로 사용한다. + +## `Object.assign()` + +```javascript +Object.assign(target, ...sources) +``` + + +`target`에 `sources`의 열거가능(`enumerable`)하고, 객체가 가진 속성(`own property`)을 할당한다. 이 때, 이 복사는 shallow copy이다. + + + + + + + + + +## 얕은 복사(shallow copy)과 깊은 복사(deep copy) + + + + + +[defineProperty MDN 공식 페이지](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) + + + From 8ab1f701816156e39ea6c8e3a2530f859de13008 Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Sat, 18 Mar 2023 19:20:39 +0900 Subject: [PATCH 05/38] =?UTF-8?q?summary=20:=20proposal-object-getownprope?= =?UTF-8?q?rtydescriptors=20appendix=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...l-object-getownpropertydescriptors-appendix.md | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/summary/proposal-object-getownpropertydescriptors-appendix.md b/src/summary/proposal-object-getownpropertydescriptors-appendix.md index 671243f..21427b2 100644 --- a/src/summary/proposal-object-getownpropertydescriptors-appendix.md +++ b/src/summary/proposal-object-getownpropertydescriptors-appendix.md @@ -228,20 +228,7 @@ Object.assign(target, ...sources) `target`에 `sources`의 열거가능(`enumerable`)하고, 객체가 가진 속성(`own property`)을 할당한다. 이 때, 이 복사는 shallow copy이다. - - - - - - - -## 얕은 복사(shallow copy)과 깊은 복사(deep copy) - - - - - -[defineProperty MDN 공식 페이지](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty) +[Object.assign MDN 공식 페이지](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) From 8ab40258b42744af3281ba93b4466508ed9d2cdf Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Mon, 20 Mar 2023 21:05:31 +0900 Subject: [PATCH 06/38] =?UTF-8?q?summary=20:=20proposal-object-getownprope?= =?UTF-8?q?rtydescriptors=20appendix=20Object.assign=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ject-getownpropertydescriptors-appendix.md | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/summary/proposal-object-getownpropertydescriptors-appendix.md b/src/summary/proposal-object-getownpropertydescriptors-appendix.md index 21427b2..727fd2c 100644 --- a/src/summary/proposal-object-getownpropertydescriptors-appendix.md +++ b/src/summary/proposal-object-getownpropertydescriptors-appendix.md @@ -225,7 +225,27 @@ Object.assign(target, ...sources) ``` -`target`에 `sources`의 열거가능(`enumerable`)하고, 객체가 가진 속성(`own property`)을 할당한다. 이 때, 이 복사는 shallow copy이다. +`target`에 `sources`의 열거가능(`enumerable`)하고, 객체가 가진 속성(`own property`)을 할당한다. 이 때, 이 복사는 shallow copy이다. +이 때, 중요한 것은 `sources`의 속성 중, `enumerable`한 속성만을 복사한다는 것이다. + +- 속성을 복사할 때, `[[Get]]`을 호출하여 속성의 값을 평가하여 `[[Set]]`을 호출하여 `target`에 속성을 할당한다. +- prototype object에 속성을 할당하는 경우 주로 `Object.defineProperty()`를 사용한다. 이 때 속성을 할당하는 로직이 `[[Set]]`, `[[Get]]`이 아닌 `[[DefineOwnProperty]]`이기 때문에 prototype object에 속성을 할당힐 때는 사용하지 않는다. +- 이 때, 로직이 다른 것도 있지만 `getter`가 선언되는 방식이 아니라 `getter`를 수행하여 나오는 값 자체를 할당하기 때문이다. + +```javascript +const obj = { + foo: 1, + get bar() { + return 2; + }, +}; + +let copy = Object.assign({}, obj); +console.log(copy); +// { foo: 1, bar: 2 } +``` + +기본적으로 `Object.assign`은 얕은 복사이다. 즉, 값만을 복사하여 할당하기 때문에 복사되는 속성이 참조형 타입일 경우 `sources`의 변경이 `target`에 영향을 줄 수 있다. [Object.assign MDN 공식 페이지](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) From 2a38a088b610c892a3926b05520b80b884366524 Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Mon, 20 Mar 2023 22:33:13 +0900 Subject: [PATCH 07/38] ko : proposal-dotAll-flag-for-reglar-expressions --- src/ko/dotAll-flag-for-regular-expressions.md | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/ko/dotAll-flag-for-regular-expressions.md diff --git a/src/ko/dotAll-flag-for-regular-expressions.md b/src/ko/dotAll-flag-for-regular-expressions.md new file mode 100644 index 0000000..4c73606 --- /dev/null +++ b/src/ko/dotAll-flag-for-regular-expressions.md @@ -0,0 +1,156 @@ +# 정규식의 `s`(dotAll) flag + + + +## 상태 + +--- + +이 제안은 [the TC39 process](https://tc39.es/process-document/) 의 4단계에 있습니다. + +
+ +## 제안 배경 + +--- + +JS의 정규식에서 마침표(`.`)는 문자의 종류와는 상관없이 단일 문자와 매칭됩니다. *ECMAScript*에서는 이 마침표(`.`)에 두가지 예외사항이 존재합니다. + +1. 마침표(`.`)는 아스트랄 문자와 매칭되지 않습니다. 이 예외사항을 해결하기 위해서는 `u` flag를 사용해야합니다. +2. 마침표(`.`)는 [line terminator characters](https://tc39.es/ecma262/#prod-LineTerminator) 와 매칭되지 않습니다. + +*ECMAScript*에서는 아래의 문자를 `line terminator characters`로 정의하고 있습니다. +- U+000A LINE FEED (LF) (`\n`) +- U+000D CARRIAGE RETURN (CR) (`\r`) +- U+2028 LINE SEPARATOR +- U+2029 PARAGRAPH SEPARATOR + +게다가 사용자 정의에 따라 더 많은 문자들이 `line terminator characters`으로 정의될 수 있습니다. 아래는 그 예시입니다. +- U+000B VERTICAL TAB (`\v`) +- U+000C FORM FEED (`\f`) +- U+0085 NEXT LINE + +두가지 예외사항로 인해 마침표(`.`)는 정규식에 있어서 문제를 발생시키게 됩니다. + +1. 구현 상, `line terminator characters`을 모두 포함하지 않기 때문에 사용자에 따라 마침표(`.`)의 매칭 여부가 달라질 수 있습니다. +2. 일반적으로 마침표(`.`)는 모든 단일 문자에 대하여 매칭된다는 의미로 사용되지만 실제로는 그렇지 않습니다. + +이러한 문제를 해결하기 위해 제안된 `s`(dotAll) flag에 대해 설명하고자 합니다. + +기존의 정규식에서는 `line terminator characters`를 포함한 모든 단일 문자를 대체하기 위해서 마침표(`.`)를 사용하지만 제대로 동작하지 않습니다. + +```javascript +/foo.bar/.test('foo\nbar'); +// → false +``` + +그래서 위의 코드 대신, `[\s\S]`나 `[^]`의 특수한 방식으로 구현해야했습니다. + +```javascript +/foo[^]bar/.test('foo\nbar'); +// → true +``` + +모든 단일 문자와의 매칭은 매우 흔하기 때문에 다른 언어들의 정규식 엔진은 마침표(`.`)를 `line terminator characters`를 포함한 모든 단일 문자와 매칭되도록 하는 모드를 제공합니다. + +- 정규식 flag로 `DOTALL` 또는 `SINGLELINE`/`s`를 제공하는 엔진들 +1. [JAVA](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL) 는 `Pattern.DOTALL`을 제공합니다. +2. [C#과 VB](https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions?redirectedfrom=MSDN&view=net-7.0) 는 `RegexOptions.Singleline`을 제공합니다. +3. Python은 `re.DOTALL`과 `re.S`를 모두 제공합니다. + +- 내장 flag 표현식 `(?s)`을 제공하는 엔진들 +1. [JAVA](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL) +2. [C#과 VB](https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-options) + +- 정규 표현식 flag `s`를 제공하는 엔진들 +1. [Perl](https://perldoc.perl.org/perlre#*s*) +2. [PHP](https://secure.php.net/manual/en/reference.pcre.pattern.modifiers.php#s) + +보편적으로, 이름을 `s`(`singleline`의 줄임)과 `dotAll`으로 사용하고 있습니다. + +하나의 예외사항으로, Ruby는 [the `m` flag(`Regexp::MULTILINE`)](https://ruby-doc.org/core-2.3.3/Regexp.html#method-i-options) 를 통해 `dotAll` 모드를 제공합니다. 안타깝게도 JS에는 `m` flag가 존재하기 때문에 하위 호환성을 고려하여 이 이름은 사용하지 않았습니다. + +## 제안된 해결책 + +--- + +*ECMAScript*의 정규식에 마침표(`.`)와 `line terminator characters`를 포함한 모든 단일 문자를 매칭하는 `s` flag를 새로 도입하고자 합니다. + +```javascript +/foo.bar/s.test('foo\nbar'); +// → true +``` + +
+ +## 상위 API에서의 활용 + +--- + +```javascript +const re = /foo.bar/s; // Or, `const re = new RegExp('foo.bar', 's');`. +re.test('foo\nbar'); +// → true +re.dotAll +// → true +re.flags +// → 's' +``` + +
+ +### FAQ + + +#### 하위 호환성은 어떤가요? + +새롭게 제안된 `s` flag는 기존과는 다른 로직을 필요로 하기 때문에 기존의 다른 정규식 패턴은 영향을 받지 않습니다. + +
+ + +#### `dotAll` 모드는 `multiline` 모드에 영향을 줄 수 있나요? + +이 질문은 `s` flag가 `m`/`multiline`flag의 반대인 `singleline`모드를 의미하는 것으로 오해하기 때문에 발생하고 있지만 실제로는 그렇지 않습니다. +이 것은 단순히 보편적으로 사용하고 있는 네이밍 방식을 차용하였기 때문에 그렇습니다. +보편적으로 사용되는 이름과는 다른 flag의 이름을 사용하게되면 의미의 혼란을 줄 수 있고, `dotAll`이라는 이름이 조금 더 명확한 의미를 담고 있기 때문입니다. +이 때문에 이 모드를 `singleline` 모드 대신 `dotAll` 모드로 사용하도록 권장하고 있습니다. + +`dotAll`와 `multiline` 두 모드는 독립적으로 동작하기 때문에 함께 사용이 가능합니다. 실제로 `multiline`은 오직 `anchors`에만, `dotAll`는 마침표(`.`)에만 영향을 줍니다. + +만약 `dotAll`와 `multiline` 두 모드를 사용하게 되면, `^`와 `$`를 문자열 내의 `line terminator characters`의 처음과 끝으로 매칭함과 동시에 마침표(`.`)는 `line terminator characters`를 포함한 모든 단일 문자에 매칭됩니다. + + +## 명세 + +--- + + +- [Ecmarkup source](https://github.com/tc39/proposal-regexp-dotall-flag/blob/main/spec.html) +- [HTML version](https://tc39.es/proposal-regexp-dotall-flag/) + +
+ +## 구현 + +--- + +- [V8](https://bugs.chromium.org/p/v8/issues/detail?id=6172), shipping in Chrome 62 +- [JavaScriptCore](https://bugs.webkit.org/show_bug.cgi?id=172634), shipping in [Safari Technology Preview 39a](https://developer.apple.com/safari/technology-preview/release-notes/) +- [XS](https://github.com/Moddable-OpenSource/moddable/blob/public/xs/sources/xsre.c), shipping in Moddable as of [the January 17, 2018 update](http://blog.moddable.tech/blog/january-17-2017-big-update-to-moddable-sdk/) +- [regexpu (transpiler)](https://github.com/mathiasbynens/regexpu) with the`{ dotAllFlag: true }`option enabled + - [online demo](https://mothereff.in/regexpu#input=const+regex+%3D+/foo.bar/s%3B%0Aconsole.log%28%0A++regex.test%28%27foo%5Cnbar%27%29%0A%29%3B%0A//+%E2%86%92+true&dotAllFlag=1) + - [Babel plugin](https://github.com/mathiasbynens/babel-plugin-transform-dotall-regex) +- [Compat-transpiler of RegExp Tree](https://github.com/dmitrysoshnikov/regexp-tree#using-compat-transpiler-api) + - [Babel plugin](https://github.com/dmitrysoshnikov/babel-plugin-transform-modern-regexp) + + + + + + + + + + + From 193181ce63c62357e7fbd2c00ea849a157fc1bab Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Mon, 20 Mar 2023 22:39:51 +0900 Subject: [PATCH 08/38] =?UTF-8?q?delete=20:=20proposal-dotAll-flag-for-reg?= =?UTF-8?q?lar-expressions=20branch=20=EB=B6=84=EB=A6=AC=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ko/dotAll-flag-for-regular-expressions.md | 156 ------------------ 1 file changed, 156 deletions(-) delete mode 100644 src/ko/dotAll-flag-for-regular-expressions.md diff --git a/src/ko/dotAll-flag-for-regular-expressions.md b/src/ko/dotAll-flag-for-regular-expressions.md deleted file mode 100644 index 4c73606..0000000 --- a/src/ko/dotAll-flag-for-regular-expressions.md +++ /dev/null @@ -1,156 +0,0 @@ -# 정규식의 `s`(dotAll) flag - - - -## 상태 - ---- - -이 제안은 [the TC39 process](https://tc39.es/process-document/) 의 4단계에 있습니다. - -
- -## 제안 배경 - ---- - -JS의 정규식에서 마침표(`.`)는 문자의 종류와는 상관없이 단일 문자와 매칭됩니다. *ECMAScript*에서는 이 마침표(`.`)에 두가지 예외사항이 존재합니다. - -1. 마침표(`.`)는 아스트랄 문자와 매칭되지 않습니다. 이 예외사항을 해결하기 위해서는 `u` flag를 사용해야합니다. -2. 마침표(`.`)는 [line terminator characters](https://tc39.es/ecma262/#prod-LineTerminator) 와 매칭되지 않습니다. - -*ECMAScript*에서는 아래의 문자를 `line terminator characters`로 정의하고 있습니다. -- U+000A LINE FEED (LF) (`\n`) -- U+000D CARRIAGE RETURN (CR) (`\r`) -- U+2028 LINE SEPARATOR -- U+2029 PARAGRAPH SEPARATOR - -게다가 사용자 정의에 따라 더 많은 문자들이 `line terminator characters`으로 정의될 수 있습니다. 아래는 그 예시입니다. -- U+000B VERTICAL TAB (`\v`) -- U+000C FORM FEED (`\f`) -- U+0085 NEXT LINE - -두가지 예외사항로 인해 마침표(`.`)는 정규식에 있어서 문제를 발생시키게 됩니다. - -1. 구현 상, `line terminator characters`을 모두 포함하지 않기 때문에 사용자에 따라 마침표(`.`)의 매칭 여부가 달라질 수 있습니다. -2. 일반적으로 마침표(`.`)는 모든 단일 문자에 대하여 매칭된다는 의미로 사용되지만 실제로는 그렇지 않습니다. - -이러한 문제를 해결하기 위해 제안된 `s`(dotAll) flag에 대해 설명하고자 합니다. - -기존의 정규식에서는 `line terminator characters`를 포함한 모든 단일 문자를 대체하기 위해서 마침표(`.`)를 사용하지만 제대로 동작하지 않습니다. - -```javascript -/foo.bar/.test('foo\nbar'); -// → false -``` - -그래서 위의 코드 대신, `[\s\S]`나 `[^]`의 특수한 방식으로 구현해야했습니다. - -```javascript -/foo[^]bar/.test('foo\nbar'); -// → true -``` - -모든 단일 문자와의 매칭은 매우 흔하기 때문에 다른 언어들의 정규식 엔진은 마침표(`.`)를 `line terminator characters`를 포함한 모든 단일 문자와 매칭되도록 하는 모드를 제공합니다. - -- 정규식 flag로 `DOTALL` 또는 `SINGLELINE`/`s`를 제공하는 엔진들 -1. [JAVA](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL) 는 `Pattern.DOTALL`을 제공합니다. -2. [C#과 VB](https://learn.microsoft.com/en-us/dotnet/api/system.text.regularexpressions.regexoptions?redirectedfrom=MSDN&view=net-7.0) 는 `RegexOptions.Singleline`을 제공합니다. -3. Python은 `re.DOTALL`과 `re.S`를 모두 제공합니다. - -- 내장 flag 표현식 `(?s)`을 제공하는 엔진들 -1. [JAVA](https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#DOTALL) -2. [C#과 VB](https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-options) - -- 정규 표현식 flag `s`를 제공하는 엔진들 -1. [Perl](https://perldoc.perl.org/perlre#*s*) -2. [PHP](https://secure.php.net/manual/en/reference.pcre.pattern.modifiers.php#s) - -보편적으로, 이름을 `s`(`singleline`의 줄임)과 `dotAll`으로 사용하고 있습니다. - -하나의 예외사항으로, Ruby는 [the `m` flag(`Regexp::MULTILINE`)](https://ruby-doc.org/core-2.3.3/Regexp.html#method-i-options) 를 통해 `dotAll` 모드를 제공합니다. 안타깝게도 JS에는 `m` flag가 존재하기 때문에 하위 호환성을 고려하여 이 이름은 사용하지 않았습니다. - -## 제안된 해결책 - ---- - -*ECMAScript*의 정규식에 마침표(`.`)와 `line terminator characters`를 포함한 모든 단일 문자를 매칭하는 `s` flag를 새로 도입하고자 합니다. - -```javascript -/foo.bar/s.test('foo\nbar'); -// → true -``` - -
- -## 상위 API에서의 활용 - ---- - -```javascript -const re = /foo.bar/s; // Or, `const re = new RegExp('foo.bar', 's');`. -re.test('foo\nbar'); -// → true -re.dotAll -// → true -re.flags -// → 's' -``` - -
- -### FAQ - - -#### 하위 호환성은 어떤가요? - -새롭게 제안된 `s` flag는 기존과는 다른 로직을 필요로 하기 때문에 기존의 다른 정규식 패턴은 영향을 받지 않습니다. - -
- - -#### `dotAll` 모드는 `multiline` 모드에 영향을 줄 수 있나요? - -이 질문은 `s` flag가 `m`/`multiline`flag의 반대인 `singleline`모드를 의미하는 것으로 오해하기 때문에 발생하고 있지만 실제로는 그렇지 않습니다. -이 것은 단순히 보편적으로 사용하고 있는 네이밍 방식을 차용하였기 때문에 그렇습니다. -보편적으로 사용되는 이름과는 다른 flag의 이름을 사용하게되면 의미의 혼란을 줄 수 있고, `dotAll`이라는 이름이 조금 더 명확한 의미를 담고 있기 때문입니다. -이 때문에 이 모드를 `singleline` 모드 대신 `dotAll` 모드로 사용하도록 권장하고 있습니다. - -`dotAll`와 `multiline` 두 모드는 독립적으로 동작하기 때문에 함께 사용이 가능합니다. 실제로 `multiline`은 오직 `anchors`에만, `dotAll`는 마침표(`.`)에만 영향을 줍니다. - -만약 `dotAll`와 `multiline` 두 모드를 사용하게 되면, `^`와 `$`를 문자열 내의 `line terminator characters`의 처음과 끝으로 매칭함과 동시에 마침표(`.`)는 `line terminator characters`를 포함한 모든 단일 문자에 매칭됩니다. - - -## 명세 - ---- - - -- [Ecmarkup source](https://github.com/tc39/proposal-regexp-dotall-flag/blob/main/spec.html) -- [HTML version](https://tc39.es/proposal-regexp-dotall-flag/) - -
- -## 구현 - ---- - -- [V8](https://bugs.chromium.org/p/v8/issues/detail?id=6172), shipping in Chrome 62 -- [JavaScriptCore](https://bugs.webkit.org/show_bug.cgi?id=172634), shipping in [Safari Technology Preview 39a](https://developer.apple.com/safari/technology-preview/release-notes/) -- [XS](https://github.com/Moddable-OpenSource/moddable/blob/public/xs/sources/xsre.c), shipping in Moddable as of [the January 17, 2018 update](http://blog.moddable.tech/blog/january-17-2017-big-update-to-moddable-sdk/) -- [regexpu (transpiler)](https://github.com/mathiasbynens/regexpu) with the`{ dotAllFlag: true }`option enabled - - [online demo](https://mothereff.in/regexpu#input=const+regex+%3D+/foo.bar/s%3B%0Aconsole.log%28%0A++regex.test%28%27foo%5Cnbar%27%29%0A%29%3B%0A//+%E2%86%92+true&dotAllFlag=1) - - [Babel plugin](https://github.com/mathiasbynens/babel-plugin-transform-dotall-regex) -- [Compat-transpiler of RegExp Tree](https://github.com/dmitrysoshnikov/regexp-tree#using-compat-transpiler-api) - - [Babel plugin](https://github.com/dmitrysoshnikov/babel-plugin-transform-modern-regexp) - - - - - - - - - - - From 1104c2467d5d1a3166363c5d6a9aed12e2a84ca3 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:11:48 +0900 Subject: [PATCH 09/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index 7ddf976..bfbc4e1 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -8,7 +8,7 @@ stage 0 단계에서 **[Rick Waldron](https://github.com/rwaldron)** 이 제안 ## 적용 상태 -해당 제안은 현재 [the TC39 process](https://github.com/tc39/ecma262/)의 stage 4 단계에 있습니다. +해당 제안은 현재 [the TC39 process](https://github.com/tc39/ecma262/)의 [4 단계](https://github.com/tc39/proposals/blob/main/finished-proposals.md)에 있습니다. 해당 제안은 `Reflect.getOwnPropertyDescriptors`과 동일하나, 다른 버전과의 일관성을 위하여 `Object`의 public 정적 메서드로 구현되어있습니다. From d855099f143dee240423bba2467db49eaafee4d9 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:12:06 +0900 Subject: [PATCH 10/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index bfbc4e1..ea1c88c 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -14,7 +14,7 @@ stage 0 단계에서 **[Rick Waldron](https://github.com/rwaldron)** 이 제안 ## 제안 동기 -ECMAScript 에는 두 객체 간의 복사를 구현한 단일 메서드가 존재하지 않습니다. 복잡한 어플리케이션에 함수적 프로그래밍과 불변 객체의 필요성이 대두된 시점에서 모든 프레임워크, 라이브러리가 객체와 프로토 타입들 간의 복사를 자신만의 방식으로 각각 구현하고 있습니다. +ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존재하지 않습니다. 복잡한 어플리케이션에 함수적 프로그래밍과 불변 객체의 필요성이 대두된 시점에서 모든 프레임워크, 라이브러리가 객체와 프로토타입들 간의 복사를 자신만의 방식으로 각각 구현하고 있습니다. `Object.assign`으로 구현하게 되는 경우, 많은 혼란과 의도하지 않은 동작들이 발생하게 됩니다. 이는 복사가 단순히 **얕은 복사**이기 때문입니다. (특히 복잡한 객체나 클래스의 프로토타입의 경우, descriptors나, 접근자를 삭제하는 방식이 아닌, 속성과 symbols에 직접 접근하는 복사 방식은 문제가 될 수 있다.) From f98c490cadceff6b824b9118a2111c427959e29b Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:15:32 +0900 Subject: [PATCH 11/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index ea1c88c..3d3b6ba 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -25,7 +25,7 @@ ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존 마지막으로, 무엇보다도 두 객체간의 얕은 복사는 `Object.assign`와 거의 차이가 존재하지 않는다. -## FAQs +## 자주 묻는 질문들 ### `Reflect.getOwnPropertyDescriptors`이 꼭 있어야하나? From 46c171621e5c4004ab099f84d275eaa13fab73a5 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:15:51 +0900 Subject: [PATCH 12/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index 3d3b6ba..59cb728 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -21,7 +21,7 @@ ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존 열거형의 여부를 떠나서 모든 descriptor를 확인하는 작업은 객체가 기본적으로 비열거형 메서드와 접근자를 가지고 있기 때문에 클래스와 클래스의 프로토타입의 구성을 구현하는데 중요합니다. -또한 decorator의 경우, 다른 클래스와 믹스인의 descriptor들을 통해 확인할 수 있고 `Object.defineProperties`를 통해 쉽게 할당이 가능하다. 필요하지 않은 descriptor를 필터링하는 것은 반복적이지 않고 간단하다. +또한 decorator는 다른 클래스 또는 믹스인에서 descriptor를 한 번에 가져와`Object.defineProperties`를 통해 쉽게 할당이 가능합니다. 필요하지 않은 descriptor를 필터링하는 것도 더 간단할 뿐만 아니라 매번 덜 반복적일 수 있습니다. 마지막으로, 무엇보다도 두 객체간의 얕은 복사는 `Object.assign`와 거의 차이가 존재하지 않는다. From f59b405906391e0a9a3bf90c02623b4e4b5b6d44 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:15:59 +0900 Subject: [PATCH 13/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index 59cb728..a5f506f 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -29,7 +29,7 @@ ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존 ### `Reflect.getOwnPropertyDescriptors`이 꼭 있어야하나? -이 제안의 목적이 여러 형태의 보일러플레이트를 단순화하고, 여러개의 방법들을 일치시키기 위함이므로 현재 `Reflect.getOwnPropertyDescriptors`의 또 다른 버전으로 생각할 수 있다. +이 제안의 목적이 여러 형태의 보일러플레이트를 단순화하고, 여러개의 방법들을 일치시키기 위함이므로 현재 `Reflect.getOwnPropertyDescriptors`의 또 다른 버전으로 생각할 수 있습니다. 업데이트 : 위원회는 `Reflect`가 `Proxy`의 트랩을 미러링을 위한 것이므로 옵션이 아니라는 것을 사전에 결정하였습니다. From f0ba809fff323a6baca41033eb6d01d59db1329b Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:18:38 +0900 Subject: [PATCH 14/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index a5f506f..7853b97 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -34,7 +34,7 @@ ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존 업데이트 : 위원회는 `Reflect`가 `Proxy`의 트랩을 미러링을 위한 것이므로 옵션이 아니라는 것을 사전에 결정하였습니다. -## 제안 로직 +## 제안된 해결책 `Object.getOwnPropertyDescriptor`의 또 다른 버전으로서, 해당 제안은 제네릭 객체이 가진 모든 `descriptor`를 한번의 작업으로 탐색하는 것을 말한다. From 94405947bf164ea54cf1bada4af33061360106de Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:18:44 +0900 Subject: [PATCH 15/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index 7853b97..d50ec5d 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -36,7 +36,7 @@ ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존 ## 제안된 해결책 -`Object.getOwnPropertyDescriptor`의 또 다른 버전으로서, 해당 제안은 제네릭 객체이 가진 모든 `descriptor`를 한번의 작업으로 탐색하는 것을 말한다. +`Object.getOwnPropertyDescriptor`의 또 다른 버전으로서, 본 제안은 제네릭 객체가 가진 모든 `descriptor`를 한번의 작업으로 탐색하는 것에 관한 것입니다. 해당 제안의 **polyfill**은 아래와 같다. From 65d48600806efc3ff053ca70eeda2ac9e93c81b6 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:18:53 +0900 Subject: [PATCH 16/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index d50ec5d..ab012f2 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -38,7 +38,7 @@ ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존 `Object.getOwnPropertyDescriptor`의 또 다른 버전으로서, 본 제안은 제네릭 객체가 가진 모든 `descriptor`를 한번의 작업으로 탐색하는 것에 관한 것입니다. -해당 제안의 **polyfill**은 아래와 같다. +해당 제안의 **polyfill**은 아래와 같습니다. ```javascript if (!Object.hasOwnProperty('getOwnPropertyDescriptors')) { From d3390a0d8072048e9051286e712df4b9ddf4b4c4 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Thu, 23 Mar 2023 00:19:11 +0900 Subject: [PATCH 17/38] Update src/ko/proposal-object-getownpropertydescriptors.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-object-getownpropertydescriptors.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index ab012f2..07c1963 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -69,7 +69,7 @@ if (!Object.hasOwnProperty('getOwnPropertyDescriptors')) { ## 설명하기 위한 예제 -위의 폴리필은 ES5 또는 부분적인 ES2015를 지원하는 엔진에서 동작하는 보일러플레이트를 개선한 것이다. +위의 폴리필은 ES5 또는 부분적인 ES2015를 지원하는 엔진에서 동작하는 보일러플레이트를 개선하는 ES2015 친화적인 대안을 제시합니다. `Object.getOwnPropertyDescriptors`을 통해서 두개의 객체간 얕은 복사와 클로닝이 가능하다. 예제를 보자. From 1343deca1398f610a51b38b7639f02dc467ef1a9 Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Thu, 23 Mar 2023 01:23:50 +0900 Subject: [PATCH 18/38] =?UTF-8?q?ko=20:=20proposal-object-getownpropertyde?= =?UTF-8?q?scriptors=20=EB=B2=88=EC=97=AD=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...oposal-object-getownpropertydescriptors.md | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/src/ko/proposal-object-getownpropertydescriptors.md b/src/ko/proposal-object-getownpropertydescriptors.md index 07c1963..46367d3 100644 --- a/src/ko/proposal-object-getownpropertydescriptors.md +++ b/src/ko/proposal-object-getownpropertydescriptors.md @@ -4,39 +4,37 @@ ## 제안한 사람 -stage 0 단계에서 **[Rick Waldron](https://github.com/rwaldron)** 이 제안하였으나, 현재 공식적으로 제안한사람은 **[Jordan Harband](https://github.com/ljharb)** 입니다. +stage 0 단계에서 **[Rick Waldron](https://github.com/rwaldron)** 이 제안하였으나, 현재 공식적으로 제안한 사람은 **[Jordan Harband](https://github.com/ljharb)** 입니다. ## 적용 상태 -해당 제안은 현재 [the TC39 process](https://github.com/tc39/ecma262/)의 [4 단계](https://github.com/tc39/proposals/blob/main/finished-proposals.md)에 있습니다. +본 제안은 현재 [the TC39 process](https://github.com/tc39/ecma262/)의 [4 단계](https://github.com/tc39/proposals/blob/main/finished-proposals.md)에 있습니다. -해당 제안은 `Reflect.getOwnPropertyDescriptors`과 동일하나, 다른 버전과의 일관성을 위하여 `Object`의 public 정적 메서드로 구현되어있습니다. +본 제안은 `Reflect.getOwnPropertyDescriptors`과 동일하나, 다른 버전과의 호환을 위하여 `Object`의 public 정적 메서드로 구현되어 있습니다. ## 제안 동기 -ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존재하지 않습니다. 복잡한 어플리케이션에 함수적 프로그래밍과 불변 객체의 필요성이 대두된 시점에서 모든 프레임워크, 라이브러리가 객체와 프로토타입들 간의 복사를 자신만의 방식으로 각각 구현하고 있습니다. +ECMAScript에는 두 객체 간의 복사를 구현한 단일 메서드가 존재하지 않습니다. 어플리케이션이 점점 복잡해짐에 따라 함수적 프로그래밍과 불변 객체가 더더욱 필요하게 되었고, 많은 프레임워크와 라이브러리가 복잡한 객체와 프로토타입 간의 속성을 복사하는 보일러플레이트를 각자의 방식으로 구현하기 시작하였습니다. -`Object.assign`으로 구현하게 되는 경우, 많은 혼란과 의도하지 않은 동작들이 발생하게 됩니다. 이는 복사가 단순히 **얕은 복사**이기 때문입니다. -(특히 복잡한 객체나 클래스의 프로토타입의 경우, descriptors나, 접근자를 삭제하는 방식이 아닌, 속성과 symbols에 직접 접근하는 복사 방식은 문제가 될 수 있다.) +두 객체 간의 복사를 `Object.assign`을 사용하여 구현하게 되는 경우, 많은 혼란과 의도하지 않은 동작들이 발생하게 됩니다. 이는 `Object.assign`을 사용한 복사가 **얕은 복사**이기 때문입니다. (`Object.assign`은 객체의 속성이 가진 descriptor가 아닌 속성의 값 / symbol을 접근하여 복사하기 때문입니다.) 이렇게 속성이 가진 잠재적 accessors를 사용하지 않는 복사는 특히 복잡한 객체나 클래스의 프로토타입을 구성할 때 매우 큰 오류가 발생할 수 있습니다. -열거형의 여부를 떠나서 모든 descriptor를 확인하는 작업은 객체가 기본적으로 비열거형 메서드와 접근자를 가지고 있기 때문에 클래스와 클래스의 프로토타입의 구성을 구현하는데 중요합니다. +객체는 기본적으로 열거불가능한 메서드나 accessors가 존재하기 때문에 객체의 속성이 열거가능 여부과 무관하게 모든 descriptor를 탐색하는 로직은 클래스와 클래스의 프로토타입의 구성을 구현하는데 중요합니다. -또한 decorator는 다른 클래스 또는 믹스인에서 descriptor를 한 번에 가져와`Object.defineProperties`를 통해 쉽게 할당이 가능합니다. 필요하지 않은 descriptor를 필터링하는 것도 더 간단할 뿐만 아니라 매번 덜 반복적일 수 있습니다. +또한 decorator는 다른 클래스 또는 믹스인에서 descriptor를 한 번에 가져올 수 있고, 이 descriptor들을 통해 `Object.defineProperties`로 쉽게 속성을 정의할 수 있습니다. 불필요한 descriptor를 필터링하는 것이 더 간단해지고, 단순해질 것입니다. -마지막으로, 무엇보다도 두 객체간의 얕은 복사는 `Object.assign`와 거의 차이가 존재하지 않는다. +무엇보다도 두 객체간의 얕은 복사는 `Object.assign`로 충분히 구현 가능하기 때문입니다. ## 자주 묻는 질문들 ### `Reflect.getOwnPropertyDescriptors`이 꼭 있어야하나? -이 제안의 목적이 여러 형태의 보일러플레이트를 단순화하고, 여러개의 방법들을 일치시키기 위함이므로 현재 `Reflect.getOwnPropertyDescriptors`의 또 다른 버전으로 생각할 수 있습니다. - -업데이트 : 위원회는 `Reflect`가 `Proxy`의 트랩을 미러링을 위한 것이므로 옵션이 아니라는 것을 사전에 결정하였습니다. +이 제안의 목적은 여러 형태의 보일러플레이트를 단순화하며, 여러가지 구현 방식을 하나로 모으기 위함이기 때문에 단 하나의 방식을 제시하는 것은 아닙니다. 하지만 현재 사용되고 있는 `Reflect.getOwnPropertyDescriptors` 또한 하나의 방식으로 일치시킬 수 있을 것으로 보입니다. +업데이트 : 위원회는 `Reflect`가 `Proxy`의 트랩을 미러링을 위한 것이므로 하나의 '방식'으로 보고 있지 않습니다. ## 제안된 해결책 -`Object.getOwnPropertyDescriptor`의 또 다른 버전으로서, 본 제안은 제네릭 객체가 가진 모든 `descriptor`를 한번의 작업으로 탐색하는 것에 관한 것입니다. +`Object.getOwnPropertyDescriptor`를 사용하여 제네릭 객체가 가진 모든 `descriptor`를 한번의 작업으로 탐색하는 방법을 제안하고자 합니다. 해당 제안의 **polyfill**은 아래와 같습니다. @@ -67,11 +65,11 @@ if (!Object.hasOwnProperty('getOwnPropertyDescriptors')) { } ``` -## 설명하기 위한 예제 +## 설명하기 위한 예시 위의 폴리필은 ES5 또는 부분적인 ES2015를 지원하는 엔진에서 동작하는 보일러플레이트를 개선하는 ES2015 친화적인 대안을 제시합니다. -`Object.getOwnPropertyDescriptors`을 통해서 두개의 객체간 얕은 복사와 클로닝이 가능하다. 예제를 보자. +아래의 예제에서 보이듯, `Object.getOwnPropertyDescriptors`을 통해서 두개의 객체간 얕은 복사와 클로닝이 가능합니다. ```javascript const shallowClone = (object) => Object.create( @@ -85,7 +83,7 @@ const shallowMerge = (target, source) => Object.defineProperties( ); ``` -mixin를 통한 객체 또한 이 제안을 통해 개선이 가능하다. +믹스인을 사용하는 객체 또한 이 제안을 통해 개선이 가능합니다. ```javascript let mix = (object) => ({ @@ -102,9 +100,9 @@ let c = {c: 'c'}; let d = mix(c).with(a, b); ``` -만약 side effect를 피하고 setter/getter를 복사하며 구분 요소로 열거 가능한 속성을 사용하고자 `[[Set]]`/`[[Get]]` 대신 `[[DefineOwnProperty]]`/`[[GetOwnProperty]]`를 사용하는 방식을 `Object.assign`을 사용하여 구현하는 것을 생각해보자. +만약 얕은 복사로 인한 side effect를 피하고 `setter`/`getter`를 복사하거나, 객체간 구별된 열거가능 속성을 사용하기 위해서 `[[Set]]`/`[[Get]]` 대신 `[[DefineOwnProperty]]`/`[[GetOwnProperty]]`를 사용하는 방식을 `Object.assign`을 사용하여 구현하는 것을 생각해보겠습니다. -제안 이전에 메서드는 아래와 같이 구현될 것이다. +제안 이전에 메서드는 아래와 같이 구현됩니다. ```javascript function completeAssign(target, ...sources) { @@ -128,7 +126,7 @@ function completeAssign(target, ...sources) { } ``` -그러나 `Object.getOwnPropertyDescriptors`를 사용하게 되면, 위의 보일러 플레이트가 아래와 같이 구현 가능하게 된다. +그러나 `Object.getOwnPropertyDescriptors`를 사용하게 되면, 위의 보일러 플레이트가 아래와 같이 구현 가능하게 됩니다. ```javascript var completeAssign = (target, ...sources) => From 12733dad47afedea445ae1e15c6088a5b3434ac2 Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Thu, 23 Mar 2023 01:24:43 +0900 Subject: [PATCH 19/38] =?UTF-8?q?summary=20:=20proposal-object-getownprope?= =?UTF-8?q?rtydescriptors-appendix=20=EC=B6=94=EA=B0=80=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(=EB=AF=B8=EC=99=84)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../proposal-object-getownpropertydescriptors-appendix.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/summary/proposal-object-getownpropertydescriptors-appendix.md b/src/summary/proposal-object-getownpropertydescriptors-appendix.md index 727fd2c..cddf55c 100644 --- a/src/summary/proposal-object-getownpropertydescriptors-appendix.md +++ b/src/summary/proposal-object-getownpropertydescriptors-appendix.md @@ -101,8 +101,7 @@ console.log(j.y); // 5 ---- - -# Object를 복사하는 방법# Object에 속성을 선언하는 방법. +# Object에 속성을 선언하는 방법. ## 'property accessor', 속성의 접근자 From f4f684a4fd9aabce06d209f356f35efda4f58e92 Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Wed, 29 Mar 2023 01:19:56 +0900 Subject: [PATCH 20/38] =?UTF-8?q?ko=20:=20proposal-promise-finally=20?= =?UTF-8?q?=EB=B2=88=EC=97=AD=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ko/proposal-promise-finally.md | 44 ++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 src/ko/proposal-promise-finally.md diff --git a/src/ko/proposal-promise-finally.md b/src/ko/proposal-promise-finally.md new file mode 100644 index 0000000..2e77113 --- /dev/null +++ b/src/ko/proposal-promise-finally.md @@ -0,0 +1,44 @@ +# Promise.prototype.finally + +`Promise.prototype.finally`의 ECMAScript 제안, 스펙, 참조 문헌을 제시합니다. + +해당 스펙은 [cancelable promise proposal](https://github.com/tc39/proposal-cancelable-promises/blob/e31520fc9a53a8cbeff53b0df413d9e565b27d69/Third%20State.md#promiseprototypefinally-implementation) 에 따라 [@ljharb](https://github.com/ljharb) 에 의해 작성되었습니다. + +폴리필/shim은 [npm](https://www.npmjs.com/package/promise.prototype.finally) 에 있습니다. + +해당 제안은 현재 [process](https://tc39.es/process-document/) 상의 [stage 4](https://github.com/tc39/proposals/blob/main/finished-proposals.md) 에 있습니다. + + +# 이론적 해석 + +많은 promise 라이브러리들은 promise가 완료(`fulfilled` 또는 `rejected`)되었을 때 발생하는 콜백을 등록하는 `finally` 메서드를 가지고 있습니다. 가장 기초적인 예제는 `cleanup` 입니다. 이는 AJAX 요청 중 보여지는 "loading" 스피너를 숨기게 하고 싶다거나, 열려있는 파일을 닫게 한다거나, 어떠한 작업이 진행되었을 때 성공여부를 떠나 로그를 남기고 싶을 때를 말합니다. + +## `then(f, f)`을 사용하면 되지 않을까요? + +`promise.finally(func)`은 `promise.then(func, func)`과 유사하면서도 몇몇 중요한 차이가 존재합니다. + +- 함수를 inline 방식으로 사용하는 경우, 해당 함수를 두번 정의하거나 변수로 정의하지 않고 한번만으로 전달할 수 있습니다. +- `finally` 콜백은 promise의 성공 / 실패여부와 무관하기 때문에 어떠한 인자도 받지 않습니다. 실패 사유나 성공시 전달되는 반환 값이 필요하지 않는 경우에만 사용합니다. +- `Promise.resolve(2).then(() => {}, () => {})`은 promise가 `undefined`를 반환하며 성공하지만, `Promise.resolve(2).finally(() => {})`는 `2`를 반환하며 성공합니다. +- 유사하게 `Promise.reject(3).then(() => {}, () => {})`은 promiserk `undefined`를 반환하며 실패하지만, `Promise.reject(3).finally(() => {})`는 `3`을 반환하며 실패합니다. + + +그러나 `finally` 콜백 내의 `throw`나 rejected된 promise를 반환하는 경우, 실패 사유와 함께 새로운 promise를 `reject`할 것입니다. + +# 네이밍 + +`finally`라는 이름을 고수한 이유는, 직관적이기 때문입니다. `catch`와 마찬가지로 `finally`는 `try`/`catch`/`finally`의 구문 형식을 따르고 있습니다. (물론 `try`는 `Promise.resolve().then`과 유사성이 떨어집니다.) finally 구문은 예외 처리를 한다거나 빠르게 반환하는 것과 같이 "갑작스러운 완료"를 통해 반환 값을 수정할 수 있습니다. 하지만 `Promise#finally`는 내부에서 예외를 던짐(promise를 reject 시킴)으로서 갑작스럽게 완료시키는 것을 제외하고는, 반환값을 수정할 수 없습니다. 이는 promise의 정상 종료와 종료보다 이른 `return undefined` 간의 차이를 구별할 수 없을 뿐 만 아니라 finally 구문의 병렬 처리는 반드시 동시성에 대한 차이가 존재하기 때문입니다. + +저는 순서의 의미를 지니지 않은 단어인 `always`를 대체로 고려하였으나, 저는 통사적 변화에 대한 유사점이 설득력 있다고 생각합니다. + + +# 구현 + +- [Bluebird#finally](http://bluebirdjs.com/docs/api/finally.html) +- [Q#finally](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) +- [when#finally](https://github.com/cujojs/when/blob/master/docs/api.md#promisefinally) +- [jQuery jqXHR#always](https://api.jquery.com/jQuery.ajax/#jqXHR) + +# 스펙 + +스펙은 [markdown format](https://github.com/tc39/proposal-promise-finally/blob/main/spec.md) 으로 볼 수 있거나, [HTML](https://tc39.es/proposal-promise-finally/) 을 통해 확인이 가능합니다. \ No newline at end of file From b2c83173dee2f70efa1f8a144d9ff2a335534720 Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Thu, 1 Jun 2023 02:21:28 +0900 Subject: [PATCH 21/38] =?UTF-8?q?ko=20:=20proposal-class-fields=20?= =?UTF-8?q?=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ko/proposal-class-fields.md | 241 ++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 src/ko/proposal-class-fields.md diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md new file mode 100644 index 0000000..e4de08f --- /dev/null +++ b/src/ko/proposal-class-fields.md @@ -0,0 +1,241 @@ +# JavaScript의 클래스 필드 선언 + +Daniel Ehrenberg, Jeff Morrison + +[단계 4](https://tc39.es/process-document/) + +## 안내를 위한 예제: 클래스의 커스텀 요소 + +클릭하였을 때 증가하는 카운터 위젯을 정의하기 위해서 ES2015에서는 아래와 같이 정의할 수 있습니다. + +```js +class Counter extends HTMLElement { + clicked() { + this.x++; + window.requestAnimationFrame(this.render.bind(this)); + } + + constructor() { + super(); + this.onclick = this.clicked.bind(this); + this.x = 0; + } + + connectedCallback() { this.render(); } + + render() { + this.textContent = this.x.toString(); + } +} +window.customElements.define('num-counter', Counter); +``` + +## 필드 선언 + +the ESnext 필드 선언 제안서에서는, 위의 예제를 아래와 같이 작성할 수 있습니다. + +```js +class Counter extends HTMLElement { + x = 0; + + clicked() { + this.x++; + window.requestAnimationFrame(this.render.bind(this)); + } + + constructor() { + super(); + this.onclick = this.clicked.bind(this); + } + + connectedCallback() { this.render(); } + + render() { + this.textContent = this.x.toString(); + } +} +window.customElements.define('num-counter', Counter); +``` + +위의 예제에서처럼, `x = 0`의 문법으로 필드 선언을 한 것을 볼 수 있습니다. 또한 `x`의 초기화 없이 필드를 선언할 수 있습니다. 상위의 필드 선언을 통해서 클래스 선언문은 더 구체적인 의미를 가집니다. 선언된 필드가 항상 존재하기 때문에 인스턴스의 상태 변경이 줄어듭니다. + +## 프라이빗 속성 + +상위의 예제는 내부적으로 유지하는 것이 좋은 상세한 구현을 외부로 노출하고 있습니다. ESnext의 프라이빗 속성과 메서드들을 통해서 재정의 할 수 있습니다. + +```js +class Counter extends HTMLElement { + #x = 0; + + clicked() { + this.#x++; + window.requestAnimationFrame(this.render.bind(this)); + } + + constructor() { + super(); + this.onclick = this.clicked.bind(this); + } + + connectedCallback() { this.render(); } + + render() { + this.textContent = this.#x.toString(); + } +} +window.customElements.define('num-counter', Counter); +``` + +속성을 프라이빗으로 만들기 위해서는 속성명을 `#`으로 시작하도록 선언합니다. + +이러한 속성들을 클래스의 외부에서는 보이지 않도록 정의함으로써, ESnext는 클래스의 사용자가 실수로 내부적인 버전 변경을 하지않도록 엄격한 캡슐화를 제공합니다. + +ESnext는 프라이빗 속성을 위의 필드 선언 방식으로만 제공합니다. 프라이빗 속성들은 일반 속성이 선언될 수 있는 방식과 동일하게 나중에 임의로 선언될 수 없습니다. + +## 주요 설계 중점 사항들 + +### Object.defineProperty를 통한 퍼블릭 필드 선언 + +퍼블릭 필드 선언문은 `this.field = value;` (`[[Set]]`문법)가 아닌 인스턴스 내부의 `Object.defineProperty`(TC39 회의에서 언급된 `[[Define]]` 문법)를 통해서 인스턴스에 필드를 선언합니다. 아래는 이러한 영향의 예제입니다. + +```js +class A { + set x(value) { console.log(value); } +} +class B extends A { + x = 1; +} +``` + +채택된 문법에 따르면, `new B()`는 콘솔에 어떤 것도 출력되지 않고, `1`의 값을 가진 `x` 속성을 가진 객체가 반환됩니다. `[[Set]]` 문법을 사용하면 `1`이 콘솔에 출력되며, 속성에 접근하려고 하면 `TypeError`를 발생시킬 것입니다.(getter가 존재하지 않기 때문). + +`[[Set]]`와 `[[Define]]` 중에 선택하는 것은 대조적인 종류의 기댓값에 대한 설계상의 결정입니다. 상위 클래스가 가진 것과 관련없이 데이터 속성으로서 필드가 선언되는 것과 setter가 호출되는 것 간의 차이입니다. 아래의 긴 논의 끝에 TC39는 첫번째 예상값을 보존하는 것이 중요하다고 판단함에 따라 `[[Define]]` 문법을 사용하는 것으로 결정하였습니다. + +퍼블릭 필드를 `Object.defineProperty` 문법을 사용하기로한 결정은 TC39의 광범위한 논의와 개발자 커뮤니티에서의 상담을 기반하여 이루어졌습니다. TC39는 `Object.defineProperty`으로 강하게 의결되었으나, 안타깝게도 [커뮤니티는 분열되었습니다](https://github.com/tc39/proposal-class-fields/issues/151#issuecomment-431597270). + +마이그레이션을 위하여 [decorators 제안서](https://github.com/tc39/proposal-decorators/) 는 `[[Set]]` 문법을 사용한 퍼블릭 필드 선언을 위한 decorator 작성법을 제공합니다. 표존에 대하여 동의하지 않더라도 다른 방식은 사용가능합니다. (이 것이 TC39가 채택한 정의와 무관하게 더 적합할 수 있습니다.) + +퍼블릭 필드는 Chrome 72에서 `[[Define]]` 문법을 통해 [제공됩니다](https://www.chromestatus.com/feature/6001727933251584). 그리고 이 문법에 대한 결정은 재검토되지 않을 것 같습니다. + +### 초기화 되지 않은 필드가 `undefined`로 할당되는 것. + +퍼블릭 필드와 프라이빗 필드 모두 인스턴스 내에 속성으로 선언될 때, 초기화가 존재할 수도, 존재하지 않을 수도 있습니다. 초기화가 존재하지 않는다면, 해당 필드는 `undefined`로 할당됩니다. 이 것은 초기화가 존재하지 않는 필드 선언을 완전히 무시하는 특정 트랜스파일러 구현과 조금 다릅니다. + +예를 들어, 아래의 예제에서 `new D`의 결과는 `1`이 아닌 `undefined`의 값을 가진 `y`속성을 가진 객체일 수 있습니다. +```js +class C { + y = 1; +} +class D extends C { + y; +} +``` + +초기화가 존재하지 않는 필드를 제거하지 않고 `undefined`로 할당하는 문법은 필드 선언이 생성된 객체에 속성이 존재하는지 확인하는 작업에 대해서 신뢰성을 제공합니다. 이 것은 프로그래머가 해당 객체를 동일한 일반적인 상태로 유지할 수 있도록 도와줌으로써, 구현에 대해 더 쉽게 이해할 수 있고 최적화할 수 있도록 합니다. + +### 프라이빗 문법 + +프라이빗 필드는 해당 필드을 접근하거나 선언할 때, `#`를 사용하는 문법을 기반으로 합니다. + +```js +class X { + #foo; + method() { + console.log(this.#foo) + } +} +``` + +이 문법은 다른 프로그래밍 언어와는 조금 다름에도 불구하고 간결하면서도 직관적입니다. 이러한 문법으로 결정하기 위한 제약조건과 고려된 대안들에 대한 논의는 [프라이빗 문법 FAQ](https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md) 를 확인하세요. + +프라이빗 내장 속성명은 존재하지 않습니다: `#foo`는 프라이빗 구분자이지만, `#[foo]`는 구문 오류입니다. + +### 프라이빗을 접근하기 위한 백도어는 존재하지 않습니다. + +프라이빗 필드는 매우 강력한 캡슐화 제한을 제공합니다: getter를 제공하는 겻과 마찬가지로 코드가 노출되는 것과는 달리, 클래스의 외부에서는 프라이빗 필드에 접근하는 것이 불가능합니다. 이는 다양한 종류의 reflection과 metaprogramming을 지원하는 JavaScript의 속성과는 다르지만, 오히려 내부 구현에 대한 접근을 제공하지 않는 클로저나 `WeakMap`과는 매커니즘이 유사합니다. 이러한 결정에 대한 더 많은 정보는 [FAQ 항목](https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md#why-doesnt-this-proposal-allow-some-mechanism-for-reflecting-on--accessing-private-fields-from-outside-the-class-which-declares-them-eg-for-testing-dont-other-languages-normally-allow-that) 을 참고하세요. + +접근을 편리하게 만드는 마이그레이션 +- 구현체의 개발자 도구는 프라이빗 필드에 대한 접근을 제공할 수도 있습니다.([V8 issue](https://bugs.chromium.org/p/v8/issues/detail?id=8337)) +- [decorators 제안서](https://github.com/tc39/proposal-decorators/) 는 손쉬운 사용과 프라이빗 필드에 대한 접근을 위한 도구를 제공합니다. + +### 초기화 표현식에 대한 실행 + +퍼블릭 필드와 프라이빗 필드는 생성자가 실행되는 시점에 각각 그들의 선언문의 순서대로 인스턴스 내부에 추가됩니다. 초기화는 각 클래스 인스턴스마다 새롭게 평가됩니다. 필드는 초기화가 실행된 직후, 다음 초기화가 평가되기 직전에 인스턴스에 추가됩니다. + +**스코프**: 생성되는 인스턴스가 생성자 표현식 내부의 `this`로 바인딩 됩니다. 메서드 내부에서의 `new.target`는 할당되지 않습니다. `arguments`에 대한 참조는 초기 오류입니다. 상위 메서드인 `super.method()`는 초기화 내에서는 사용가능합니다. 하지만 상위 생성자인 `super()`를 호출하는 것은 문법 오류입니다. 클래스 내에서 async 함수/generator가 사용가능 하더라도 초기화 내에서는 `await`와 `yield`의 사용이 불가능합니다. + +필드 초기화가 평가되고 인스턴스 내에 필드가 추가될 때: +- **기본 클래스**: 파라미터 파괴 이전, 생성자의 실행 시작 시점. +- **하위 클래스**: `super()`의 반환된 직후. (`super()` 호출 방법의 유연성으로 인해 많은 구현들이 별도의 보이지 않는 `initialize()` 메서드를 만들었습니다.) + +하위 클래스에서 `super()`가 호출되지 않는 경우, 일부의 퍼블릭 및 프라이빗 필드가 인스턴스 내에 추가되지 않으며 초기화가 평가되지 않습니다. 기본 클래스에서는 생성자가 다른 것을 반환하더라도 초기화가 항상 평가됩니다. [`new.initialize`](https://github.com/littledan/proposal-new-initialize) 제안서는 기본 클래스의 `super`/`this`로 제공되지 않는 인스턴스의 필드를 프로그래밍 방식으로 추가하는 방법을 제시합니다. + +## 명세서 + +자세한 사항은 [draft 명세서](https://tc39.github.io/proposal-class-fields/) 를 참고하세요. + +## 상태 + +### TC39 합의 + +이 제안서는 2017년 7월에 [단계 3](https://tc39.github.io/process-document/) 에 도달하였습니다. 이 당시에 아래와 같은 다양한 대안에 대한 긴 논의와 광범위한 의견이 존재하였습니다. +- [JS Classes 1.1](https://github.com/zenparsing/js-classes-1.1) +- [Reconsideration of "static private"](https://github.com/tc39/proposal-static-class-features) +- [Additional use of the `private` keyword](https://gist.github.com/rauschma/a4729faa65b30a6fda46a5799016458a) +- [Private Symbols](https://github.com/zenparsing/proposal-private-symbols) + +각 제안서를 통해서 TC39 구성원들은 언어 디자인의 미래에 대한 동기, JS 개발자 피드백 및 시사점을 깊게 조사하였습니다. 이러한 사고 과정과 지속적인 공동체 참여는 이 저장소에 대한 제안서에 대한 합의로 이루어졌습니다. 합의에 따라, 구현은 이 제안서를 통하여 진행됩니다. + +### 개발 역사 + +이 문서는 [Orthogonal Classes](https://github.com/erights/Orthogonal-Classes) 와 [Class Evaluation Order](https://onedrive.live.com/view.aspx?resid=A7BBCE1FC8EE16DB!442046&app=PowerPoint&authkey=!AEeXmhZASk50KjA) 에서 일찍이 논의되었던 [퍼블릭 필드](https://tc39.github.io/proposal-class-public-fields/) 와 [프라이빗 필드](https://github.com/tc39/proposal-private-fields) 에 대한 결합된 버전을 제안하고 있습니다. +프라이빗 메서드와 데토레이터에 대한 상위 호환성에 대하여 작성되었고, 이 통합은 [unified class features proposal](https://github.com/littledan/proposal-decorators) 에 작성되었습니다. 메서드와 접근자에 대해서는 [a follow-on proposal](https://github.com/littledan/proposal-private-methods/) 에 정의되어 있습니다. + +이 제안서는 [TC39 회의](https://github.com/tc39/ecma262/blob/master/CONTRIBUTING.md) 의 발표와 논의에서 뿐만 아니라 GitHub 저장소에서도 개발되었습니다. 과거의 발표나 논의는 아래와 같습니다. + +| Date | Slides | Notes | +|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| July 2016 | [Private State](https://docs.google.com/presentation/d/1RM_DEWAYh8PmJRt02IunIRaUNjlwprXF3yPW6NltuMA/edit#slide=id.p) | [📝](https://github.com/tc39/tc39-notes/blob/master/es7/2016-07/jul-28.md#9iiib-private-state) | +| January 2017 | [Public and private class fields: Where we are and next steps](https://docs.google.com/presentation/d/1yXsRdAJO7OdxF0NmZs2N8ySSrQwKp3D77vZXbQOWbMs/edit) | [📝](https://github.com/tc39/tc39-notes/blob/master/es7/2017-01/jan-26.md#public-and-private-class-fields-daniel-ehrenberg-jeff-morrison-and-kevin-gibbons) | +| May 2017 | [Class Fields Integrated Proposal](https://drive.google.com/file/d/0B-TAClBGyqSxWHpyYmg2UnRHc28/view) | [📝](https://github.com/tc39/tc39-notes/blob/master/es8/2017-05/may-25.md#15iiib-updates-on-class-field-proposals-both-public-and-private) | +| July 2017 | [Unified Class Features: A vision of orthogonality](https://docs.google.com/presentation/d/1GZ5Rfa4T7aF7t0xJrDxRZhC49mvqG5Nm6qZ_g_qrfBY/edit#slide=id.p) | [📝](https://github.com/tc39/tc39-notes/blob/master/es8/2017-07/jul-27.md#11ivc-class-fields-for-stage-3) | +| September 2017 | [Class fields status update](https://docs.google.com/presentation/d/169hWHIKFnX8E-N90FJQS3u5xpo5Tt-s4IFdheLySVfQ/edit#slide=id.p) | [📝](https://github.com/tc39/tc39-notes/blob/master/es8/2017-09/sep-26.md#12ib-class-fields-status-update) | +| November 2017 | [Class fields, static and private](https://docs.google.com/presentation/d/1wgus0BykoVk_qqCpr0TjgO0TV0Y4ql4d9iY212phzbY/edit#slide=id.g2936c02723_0_63) | [📝](https://github.com/tc39/tc39-notes/blob/master/es8/2017-11/nov-30.md#10iva-continued-inheriting-private-static-class-elements-discussion-and-resolution) | +| November 2017 | [Class features proposals: Instance features to stage 3](https://docs.google.com/presentation/d/1wKktzSOKnVIUAnfDHgTVOlQp-O3OBtHN4dKX8--DQvc/edit#slide=id.p) | [📝](https://github.com/tc39/tc39-notes/blob/master/es8/2017-11/nov-30.md#10iva-continued-inheriting-private-static-class-elements-discussion-and-resolution) | +| November 2017 | [ASI in class field declarations](https://docs.google.com/presentation/d/1bPzE6i_Bpm6FXgzfx9XFJNHGkVcM42lux-6bUNhxpl4/edit#slide=id.p) | [📝](https://github.com/tc39/tc39-notes/blob/master/es8/2017-11/nov-30.md#10ivf-class-fields-asi-discussion-and-resolution) | +| May 2018 | [Class fields: Stage 3 status update](https://docs.google.com/presentation/d/1oDQOS9b8wnuP5-o8zInsEO9lpRbhduawAmvfRzbxkOs/edit?usp=sharing) | [📝](https://github.com/tc39/tc39-notes/blob/master/es9/2018-05/may-23.md#class-fields-status-update) | +| September 2018 | [Class fields and private methods: Stage 3 update](https://docs.google.com/presentation/d/1Q9upYkWnPjJaVc8k9q3U6NekDch8tsz7CgV-Xm55-5Y/edit#slide=id.p) | [📝](https://github.com/tc39/tc39-notes/blob/master/es9/2018-09/sept-26.md#class-fields-and-private-methods-stage-3-update) | +| January 2019 | [Private fields and methods refresher](https://docs.google.com/presentation/d/1lPEfTLk_9jjjcjJcx0IAKoaq10mv1XrTZ-pgERG5YoM/edit#slide=id.p) | [📝](https://github.com/tc39/tc39-notes/blob/master/meetings/2019-01/jan-30.md#private-fields-and-methods-refresher) | + +### 구현 + +아래의 구현을 통하여 클래스 필드의 제안서를 경험할 수 있습니다: + +- Babel [7.0+](https://babeljs.io/blog/2018/08/27/7.0.0#tc39-proposals-https-githubcom-tc39-proposals-support) +- [Node 12](https://nodejs.org/en/blog/release/v12.0.0/) +- Chrome/V8 + - Public fields are [enabled](https://www.chromestatus.com/feature/6001727933251584) in Chrome 72 / V8 7.2 + - Private fields are [enabled](https://www.chromestatus.com/feature/6035156464828416) in Chrome 74 / V8 7.4 +- Firefox/SpiderMonkey + - Public instance fields are [enabled](https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/69#JavaScript) in Firefox 69 + - Public static fields are [enabled](https://wiki.developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/75#JavaScript) in Firefox 75 +- Safari/JSC + - Public instance fields are [enabled](https://developer.apple.com/documentation/safari-release-notes/safari-14-release-notes#JavaScript) in Safari 14 + - Public static fields are [enabled](https://webkit.org/blog/11364/release-notes-for-safari-technology-preview-117/) in Safari Technology Preview 117 + - Private fields are [enabled](https://webkit.org/blog/11364/release-notes-for-safari-technology-preview-117/) in Safari Technology Preview 117 +- [Moddable XS](https://blog.moddable.com/blog/secureprivate/) +- [QuickJS](https://www.freelists.org/post/quickjs-devel/New-release,82) +- [TypeScript 3.8](https://devblogs.microsoft.com/typescript/announcing-typescript-3-8/#ecmascript-private-fields) + +진행중인 구현: +- Firefox/SpiderMonkey: [Private instance fields](https://bugzilla.mozilla.org/show_bug.cgi?id=1562054) +- [Additional tooling support](https://github.com/tc39/proposal-class-fields/issues/57) + +### 이 저장소에 대한 활동에 대한 환영 + +이 저장소에 issue나 PR을 등록하는 것을 환영합니다. +- 제안서, 구문이 어떻게 작동하는지, 의미론의 의미 등에 대해 질문합니다. +- 구현 및 테스트 경험과 그 과정에서 발생하는 문제에 대해 논의합니다. +- 개선된 문서, 샘플 코드 및 모든 수준의 프로그래머를 이 기능에 도입할 수 있는 기타 방법을 개발합니다. + +JavaScript를 개선하는 방법이나 아이디어가 있는 경우, 어떻게 포함하는 가에 대한 ecma262의 [CONTRIBUTING.md](https://github.com/tc39/ecma262/blob/master/CONTRIBUTING.md) 를 참고하세요. \ No newline at end of file From d97271ec58002f1fdf819c19f2eb9535467da7a7 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:36:50 +0900 Subject: [PATCH 22/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index e4de08f..f04dc5b 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -88,7 +88,7 @@ window.customElements.define('num-counter', Counter); 속성을 프라이빗으로 만들기 위해서는 속성명을 `#`으로 시작하도록 선언합니다. -이러한 속성들을 클래스의 외부에서는 보이지 않도록 정의함으로써, ESnext는 클래스의 사용자가 실수로 내부적인 버전 변경을 하지않도록 엄격한 캡슐화를 제공합니다. +이러한 속성들을 클래스의 외부에서는 보이지 않도록 정의함으로써, ESnext는 클래스의 사용자가 실수로 내부적인 버전 변경을 하지 않도록 엄격한 캡슐화를 제공합니다. ESnext는 프라이빗 속성을 위의 필드 선언 방식으로만 제공합니다. 프라이빗 속성들은 일반 속성이 선언될 수 있는 방식과 동일하게 나중에 임의로 선언될 수 없습니다. From 5b21f4ebb54fc9f233889714080a39536b888b77 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:36:57 +0900 Subject: [PATCH 23/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index f04dc5b..8d699b8 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -113,7 +113,7 @@ class B extends A { 퍼블릭 필드를 `Object.defineProperty` 문법을 사용하기로한 결정은 TC39의 광범위한 논의와 개발자 커뮤니티에서의 상담을 기반하여 이루어졌습니다. TC39는 `Object.defineProperty`으로 강하게 의결되었으나, 안타깝게도 [커뮤니티는 분열되었습니다](https://github.com/tc39/proposal-class-fields/issues/151#issuecomment-431597270). -마이그레이션을 위하여 [decorators 제안서](https://github.com/tc39/proposal-decorators/) 는 `[[Set]]` 문법을 사용한 퍼블릭 필드 선언을 위한 decorator 작성법을 제공합니다. 표존에 대하여 동의하지 않더라도 다른 방식은 사용가능합니다. (이 것이 TC39가 채택한 정의와 무관하게 더 적합할 수 있습니다.) +마이그레이션을 위하여 [decorators 제안서](https://github.com/tc39/proposal-decorators/)는 `[[Set]]` 문법을 사용하여 퍼블릭 필드 선언을 하기 위한 decorator 작성법을 제공합니다. 표준에 대하여 동의하지 않더라도 다른 방식은 사용 가능합니다. (이것이 TC39가 채택한 정의와 무관하게 더 적합할 수 있습니다.) 퍼블릭 필드는 Chrome 72에서 `[[Define]]` 문법을 통해 [제공됩니다](https://www.chromestatus.com/feature/6001727933251584). 그리고 이 문법에 대한 결정은 재검토되지 않을 것 같습니다. From 6146118b39ee1097bbc480a3ade6110e9b084e4e Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:37:20 +0900 Subject: [PATCH 24/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 8d699b8..500faf6 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -119,7 +119,7 @@ class B extends A { ### 초기화 되지 않은 필드가 `undefined`로 할당되는 것. -퍼블릭 필드와 프라이빗 필드 모두 인스턴스 내에 속성으로 선언될 때, 초기화가 존재할 수도, 존재하지 않을 수도 있습니다. 초기화가 존재하지 않는다면, 해당 필드는 `undefined`로 할당됩니다. 이 것은 초기화가 존재하지 않는 필드 선언을 완전히 무시하는 특정 트랜스파일러 구현과 조금 다릅니다. +퍼블릭 필드와 프라이빗 필드 모두 인스턴스 내에 속성으로 선언될 때, 초기화가 존재할 수도, 존재하지 않을 수도 있습니다. 초기화가 존재하지 않는다면, 해당 필드는 `undefined`로 할당됩니다. 이것은 초기화가 존재하지 않는 필드 선언을 완전히 무시하는 특정 트랜스파일러 구현과 조금 다릅니다. 예를 들어, 아래의 예제에서 `new D`의 결과는 `1`이 아닌 `undefined`의 값을 가진 `y`속성을 가진 객체일 수 있습니다. ```js From 818954d418dc053acf88f082e94c7d6b1d0ce19d Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:37:29 +0900 Subject: [PATCH 25/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 500faf6..fd9e46e 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -131,7 +131,7 @@ class D extends C { } ``` -초기화가 존재하지 않는 필드를 제거하지 않고 `undefined`로 할당하는 문법은 필드 선언이 생성된 객체에 속성이 존재하는지 확인하는 작업에 대해서 신뢰성을 제공합니다. 이 것은 프로그래머가 해당 객체를 동일한 일반적인 상태로 유지할 수 있도록 도와줌으로써, 구현에 대해 더 쉽게 이해할 수 있고 최적화할 수 있도록 합니다. +초기화가 존재하지 않는 필드를 제거하지 않고 `undefined`로 할당하는 문법은 필드 선언이 생성된 객체에 속성이 존재하는지 확인하는 작업에 대해서 신뢰성을 제공합니다. 이것은 프로그래머가 해당 객체를 동일한 일반적인 상태로 유지할 수 있도록 도와줌으로써, 구현에 대해 더 쉽게 이해할 수 있고 최적화할 수 있도록 합니다. ### 프라이빗 문법 From 6b2c12f8844391f91439d00a2b7249e8fbfebfca Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:37:55 +0900 Subject: [PATCH 26/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index fd9e46e..95b76e7 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -135,7 +135,7 @@ class D extends C { ### 프라이빗 문법 -프라이빗 필드는 해당 필드을 접근하거나 선언할 때, `#`를 사용하는 문법을 기반으로 합니다. +프라이빗 필드는 해당 필드를 접근하거나 선언할 때, `#`를 사용하는 문법을 기반으로 합니다. ```js class X { From 7c9b567b231fc3e3a8c09df6da212e1858c5bdd0 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:38:06 +0900 Subject: [PATCH 27/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 95b76e7..5bc49ae 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -146,7 +146,7 @@ class X { } ``` -이 문법은 다른 프로그래밍 언어와는 조금 다름에도 불구하고 간결하면서도 직관적입니다. 이러한 문법으로 결정하기 위한 제약조건과 고려된 대안들에 대한 논의는 [프라이빗 문법 FAQ](https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md) 를 확인하세요. +이 문법은 다른 프로그래밍 언어와는 조금 다름에도 불구하고 간결하면서도 직관적입니다. 이러한 문법으로 결정하기 위한 제약 조건과 고려된 대안들에 대한 논의는 [프라이빗 문법 FAQ](https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md) 를 확인하세요. 프라이빗 내장 속성명은 존재하지 않습니다: `#foo`는 프라이빗 구분자이지만, `#[foo]`는 구문 오류입니다. From 72ba2096f2f0c4dcc5474967c5ff0b556b00529d Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:38:18 +0900 Subject: [PATCH 28/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 5bc49ae..a0e554f 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -148,7 +148,7 @@ class X { 이 문법은 다른 프로그래밍 언어와는 조금 다름에도 불구하고 간결하면서도 직관적입니다. 이러한 문법으로 결정하기 위한 제약 조건과 고려된 대안들에 대한 논의는 [프라이빗 문법 FAQ](https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md) 를 확인하세요. -프라이빗 내장 속성명은 존재하지 않습니다: `#foo`는 프라이빗 구분자이지만, `#[foo]`는 구문 오류입니다. +프라이빗 내장 속성명은 존재하지 않습니다. `#foo`는 프라이빗 구분자이지만, `#[foo]`는 구문 오류입니다. ### 프라이빗을 접근하기 위한 백도어는 존재하지 않습니다. From 20049b6441181011629b48e5bae419549fc76ae4 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:38:30 +0900 Subject: [PATCH 29/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index a0e554f..5f74481 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -152,7 +152,7 @@ class X { ### 프라이빗을 접근하기 위한 백도어는 존재하지 않습니다. -프라이빗 필드는 매우 강력한 캡슐화 제한을 제공합니다: getter를 제공하는 겻과 마찬가지로 코드가 노출되는 것과는 달리, 클래스의 외부에서는 프라이빗 필드에 접근하는 것이 불가능합니다. 이는 다양한 종류의 reflection과 metaprogramming을 지원하는 JavaScript의 속성과는 다르지만, 오히려 내부 구현에 대한 접근을 제공하지 않는 클로저나 `WeakMap`과는 매커니즘이 유사합니다. 이러한 결정에 대한 더 많은 정보는 [FAQ 항목](https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md#why-doesnt-this-proposal-allow-some-mechanism-for-reflecting-on--accessing-private-fields-from-outside-the-class-which-declares-them-eg-for-testing-dont-other-languages-normally-allow-that) 을 참고하세요. +프라이빗 필드는 매우 강력한 캡슐화 제한을 제공합니다. getter를 제공하는 겻과 마찬가지로 코드가 노출되는 것과는 달리, 클래스의 외부에서는 프라이빗 필드에 접근하는 것이 불가능합니다. 이는 다양한 종류의 reflection과 metaprogramming을 지원하는 JavaScript의 속성과는 다르지만, 오히려 내부 구현에 대한 접근을 제공하지 않는 클로저나 `WeakMap`과는 매커니즘이 유사합니다. 이러한 결정에 대한 더 많은 정보는 [FAQ 항목](https://github.com/tc39/proposal-class-fields/blob/master/PRIVATE_SYNTAX_FAQ.md#why-doesnt-this-proposal-allow-some-mechanism-for-reflecting-on--accessing-private-fields-from-outside-the-class-which-declares-them-eg-for-testing-dont-other-languages-normally-allow-that) 을 참고하세요. 접근을 편리하게 만드는 마이그레이션 - 구현체의 개발자 도구는 프라이빗 필드에 대한 접근을 제공할 수도 있습니다.([V8 issue](https://bugs.chromium.org/p/v8/issues/detail?id=8337)) From 6bbfea0e2c8c49ef9f8dbff27b9a7ad48da851c2 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:38:39 +0900 Subject: [PATCH 30/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 5f74481..41e0a8a 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -178,7 +178,7 @@ class X { ### TC39 합의 -이 제안서는 2017년 7월에 [단계 3](https://tc39.github.io/process-document/) 에 도달하였습니다. 이 당시에 아래와 같은 다양한 대안에 대한 긴 논의와 광범위한 의견이 존재하였습니다. +이 제안서는 2017년 7월에 [단계 3](https://tc39.github.io/process-document/)에 도달하였습니다. 이 당시에 아래와 같은 다양한 대안에 대한 긴 논의와 광범위한 의견이 존재하였습니다. - [JS Classes 1.1](https://github.com/zenparsing/js-classes-1.1) - [Reconsideration of "static private"](https://github.com/tc39/proposal-static-class-features) - [Additional use of the `private` keyword](https://gist.github.com/rauschma/a4729faa65b30a6fda46a5799016458a) From 9eefac83b26ed36f98aa0c4c477f06d7bbbeb13d Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:38:48 +0900 Subject: [PATCH 31/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 41e0a8a..14ca9ab 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -191,7 +191,7 @@ class X { 이 문서는 [Orthogonal Classes](https://github.com/erights/Orthogonal-Classes) 와 [Class Evaluation Order](https://onedrive.live.com/view.aspx?resid=A7BBCE1FC8EE16DB!442046&app=PowerPoint&authkey=!AEeXmhZASk50KjA) 에서 일찍이 논의되었던 [퍼블릭 필드](https://tc39.github.io/proposal-class-public-fields/) 와 [프라이빗 필드](https://github.com/tc39/proposal-private-fields) 에 대한 결합된 버전을 제안하고 있습니다. 프라이빗 메서드와 데토레이터에 대한 상위 호환성에 대하여 작성되었고, 이 통합은 [unified class features proposal](https://github.com/littledan/proposal-decorators) 에 작성되었습니다. 메서드와 접근자에 대해서는 [a follow-on proposal](https://github.com/littledan/proposal-private-methods/) 에 정의되어 있습니다. -이 제안서는 [TC39 회의](https://github.com/tc39/ecma262/blob/master/CONTRIBUTING.md) 의 발표와 논의에서 뿐만 아니라 GitHub 저장소에서도 개발되었습니다. 과거의 발표나 논의는 아래와 같습니다. +이 제안서는 [TC39 회의](https://github.com/tc39/ecma262/blob/master/CONTRIBUTING.md)의 발표와 논의에서 뿐만 아니라 GitHub 저장소에서도 개발되었습니다. 과거의 발표나 논의는 아래와 같습니다. | Date | Slides | Notes | |----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------| From de96feabdd86a53bf88555a1cc14a9658c976744 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:39:04 +0900 Subject: [PATCH 32/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 14ca9ab..dfc7fbf 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -162,7 +162,7 @@ class X { 퍼블릭 필드와 프라이빗 필드는 생성자가 실행되는 시점에 각각 그들의 선언문의 순서대로 인스턴스 내부에 추가됩니다. 초기화는 각 클래스 인스턴스마다 새롭게 평가됩니다. 필드는 초기화가 실행된 직후, 다음 초기화가 평가되기 직전에 인스턴스에 추가됩니다. -**스코프**: 생성되는 인스턴스가 생성자 표현식 내부의 `this`로 바인딩 됩니다. 메서드 내부에서의 `new.target`는 할당되지 않습니다. `arguments`에 대한 참조는 초기 오류입니다. 상위 메서드인 `super.method()`는 초기화 내에서는 사용가능합니다. 하지만 상위 생성자인 `super()`를 호출하는 것은 문법 오류입니다. 클래스 내에서 async 함수/generator가 사용가능 하더라도 초기화 내에서는 `await`와 `yield`의 사용이 불가능합니다. +**스코프**: 생성되는 인스턴스가 생성자 표현식 내부의 `this`로 바인딩 됩니다. 메서드 내부에서의 `new.target`는 할당되지 않습니다. `arguments`에 대한 참조는 초기 오류입니다. 상위 메서드인 `super.method()`는 초기화 내에서는 사용 가능 합니다. 하지만 상위 생성자인 `super()`를 호출하는 것은 문법 오류입니다. 클래스 내에서 async 함수/generator가 사용가능 하더라도 초기화 내에서는 `await`와 `yield`의 사용이 불가능합니다. 필드 초기화가 평가되고 인스턴스 내에 필드가 추가될 때: - **기본 클래스**: 파라미터 파괴 이전, 생성자의 실행 시작 시점. From 7765d45b194d401931f16790fa54e5ed1b4f9230 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:39:40 +0900 Subject: [PATCH 33/38] Update src/ko/proposal-class-fields.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index dfc7fbf..2d3f522 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -90,7 +90,7 @@ window.customElements.define('num-counter', Counter); 이러한 속성들을 클래스의 외부에서는 보이지 않도록 정의함으로써, ESnext는 클래스의 사용자가 실수로 내부적인 버전 변경을 하지 않도록 엄격한 캡슐화를 제공합니다. -ESnext는 프라이빗 속성을 위의 필드 선언 방식으로만 제공합니다. 프라이빗 속성들은 일반 속성이 선언될 수 있는 방식과 동일하게 나중에 임의로 선언될 수 없습니다. +ESnext는 프라이빗 속성을 위의 필드 선언 방식으로만 제공합니다. 프라이빗 속성은 일반 속성과 달리 나중에 임의로 할당하여 생성할 수 없습니다. ## 주요 설계 중점 사항들 From 8d9333f28b5323c1ab62b58e3331c1d4e08be034 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:39:46 +0900 Subject: [PATCH 34/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 2d3f522..4cfbb6c 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -189,7 +189,7 @@ class X { ### 개발 역사 이 문서는 [Orthogonal Classes](https://github.com/erights/Orthogonal-Classes) 와 [Class Evaluation Order](https://onedrive.live.com/view.aspx?resid=A7BBCE1FC8EE16DB!442046&app=PowerPoint&authkey=!AEeXmhZASk50KjA) 에서 일찍이 논의되었던 [퍼블릭 필드](https://tc39.github.io/proposal-class-public-fields/) 와 [프라이빗 필드](https://github.com/tc39/proposal-private-fields) 에 대한 결합된 버전을 제안하고 있습니다. -프라이빗 메서드와 데토레이터에 대한 상위 호환성에 대하여 작성되었고, 이 통합은 [unified class features proposal](https://github.com/littledan/proposal-decorators) 에 작성되었습니다. 메서드와 접근자에 대해서는 [a follow-on proposal](https://github.com/littledan/proposal-private-methods/) 에 정의되어 있습니다. +프라이빗 메서드와 데코레이터에 대한 상위 호환성에 대하여 작성되었고, 이 통합은 [unified class features proposal](https://github.com/littledan/proposal-decorators) 에 작성되었습니다. 메서드와 접근자에 대해서는 [a follow-on proposal](https://github.com/littledan/proposal-private-methods/) 에 정의되어 있습니다. 이 제안서는 [TC39 회의](https://github.com/tc39/ecma262/blob/master/CONTRIBUTING.md)의 발표와 논의에서 뿐만 아니라 GitHub 저장소에서도 개발되었습니다. 과거의 발표나 논의는 아래와 같습니다. From 8b8b67415b163027f1ecc17b0ca4d8709a4d8d6c Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:40:24 +0900 Subject: [PATCH 35/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 4cfbb6c..3ae8b78 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -227,7 +227,7 @@ class X { - [QuickJS](https://www.freelists.org/post/quickjs-devel/New-release,82) - [TypeScript 3.8](https://devblogs.microsoft.com/typescript/announcing-typescript-3-8/#ecmascript-private-fields) -진행중인 구현: +진행중인 구현은 다음과 같습니다. - Firefox/SpiderMonkey: [Private instance fields](https://bugzilla.mozilla.org/show_bug.cgi?id=1562054) - [Additional tooling support](https://github.com/tc39/proposal-class-fields/issues/57) From 86a0db75e22421d4e04dbeca78ea14b807705536 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:40:30 +0900 Subject: [PATCH 36/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index 3ae8b78..f011b44 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -209,7 +209,7 @@ class X { ### 구현 -아래의 구현을 통하여 클래스 필드의 제안서를 경험할 수 있습니다: +아래의 구현을 통하여 클래스 필드의 제안서를 경험할 수 있습니다. - Babel [7.0+](https://babeljs.io/blog/2018/08/27/7.0.0#tc39-proposals-https-githubcom-tc39-proposals-support) - [Node 12](https://nodejs.org/en/blog/release/v12.0.0/) From 6fb8225777da6149bd219563f3713a1257211baf Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:40:46 +0900 Subject: [PATCH 37/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index f011b44..d1493d9 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -164,7 +164,7 @@ class X { **스코프**: 생성되는 인스턴스가 생성자 표현식 내부의 `this`로 바인딩 됩니다. 메서드 내부에서의 `new.target`는 할당되지 않습니다. `arguments`에 대한 참조는 초기 오류입니다. 상위 메서드인 `super.method()`는 초기화 내에서는 사용 가능 합니다. 하지만 상위 생성자인 `super()`를 호출하는 것은 문법 오류입니다. 클래스 내에서 async 함수/generator가 사용가능 하더라도 초기화 내에서는 `await`와 `yield`의 사용이 불가능합니다. -필드 초기화가 평가되고 인스턴스 내에 필드가 추가될 때: +필드 초기화가 평가되고 인스턴스 내에 필드가 추가되는 경우는 다음과 같습니다. - **기본 클래스**: 파라미터 파괴 이전, 생성자의 실행 시작 시점. - **하위 클래스**: `super()`의 반환된 직후. (`super()` 호출 방법의 유연성으로 인해 많은 구현들이 별도의 보이지 않는 `initialize()` 메서드를 만들었습니다.) From 706f6a5b73bb49c7e8ea9d698e987353d001518f Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Fri, 8 Sep 2023 16:40:54 +0900 Subject: [PATCH 38/38] Update src/ko/proposal-class-fields.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-class-fields.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-class-fields.md b/src/ko/proposal-class-fields.md index d1493d9..302e19d 100644 --- a/src/ko/proposal-class-fields.md +++ b/src/ko/proposal-class-fields.md @@ -172,7 +172,7 @@ class X { ## 명세서 -자세한 사항은 [draft 명세서](https://tc39.github.io/proposal-class-fields/) 를 참고하세요. +자세한 사항은 [draft 명세서](https://tc39.github.io/proposal-class-fields/)를 참고하세요. ## 상태