From 3900c8899b2111dc8ecced8365ddc591ff1ded26 Mon Sep 17 00:00:00 2001 From: 1101707 Date: Wed, 15 Mar 2023 01:21:54 +0900 Subject: [PATCH 01/22] =?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/22] =?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/22] =?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/22] =?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/22] =?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/22] =?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/22] 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/22] =?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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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/22] 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/22] =?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/22] =?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/22] =?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 172f6a662e782b50820eaa9720fcbf9cc3f458cc Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Wed, 28 Jun 2023 00:07:25 +0900 Subject: [PATCH 21/22] =?UTF-8?q?ko=20:=20replaceAll=20=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ko/proposal-string-replaceall.md | 110 +++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 src/ko/proposal-string-replaceall.md diff --git a/src/ko/proposal-string-replaceall.md b/src/ko/proposal-string-replaceall.md new file mode 100644 index 0000000..2dd8002 --- /dev/null +++ b/src/ko/proposal-string-replaceall.md @@ -0,0 +1,110 @@ +# `String.prototype.replaceAll` 제안서 + +## 상태 + +제안한 사람: Mathias Bynens (Google, @mathiasbynens). + +이 제안서는 [the TC39 과정](https://tc39.es/process-document/) 중 4단계에 있으며, ES2021에 포함될 예정입니다. + +## 제안 동기 + +([우리의 TL;DR 설명자](https://v8.dev/features/string-replaceall) 또한 확인하세요.) + +현재 전역 정규식을 사용하지 않고 문자열에서 부분 문자열의 모든 인스턴스를 대체하는 방법은 없습니다. +`String.prototype.replace`는 문자열 인자와 함께 사용될 때 오직 첫 번째 항목에만 영향을 줍니다. 개발자들이 JS 내에서 이러한 작업을 하려고 한다는 많은 증거가 있습니다. - [StackOverflow 질문](https://stackoverflow.com/q/1144783/96656) 의 수천개의 투표를 보세요. + +현재 이 작업을 구현하기 위한 대부분의 방식은 전역 정규식을 사용하는 것입니다. + +```js +const queryString = 'q=query+string+parameters'; +const withSpaces = queryString.replace(/\+/g, ' '); +``` + +이 접근은 특수 정규식 문자를 이스케이프해야 하는 단점이 있습니다. - `'+'`가 이스케이프 된 것을 보세요. + +대체안은 `String#split`과 `Array#join`을 결합하는 것입니다. + +```js +const queryString = 'q=query+string+parameters'; +const withSpaces = queryString.split('+').join(' '); +``` + +이 접근은 이스케이핑을 피할 수 있으나 문자열을 부분들의 배열로 나누고, 이 것을 다시 하나로 붙여야하는 오버헤드가 존재합니다. + +## 제안된 해결방식 + +우리는 String 프로토타입에 새로운 메서드의 추가를 제안합니다. - `replaceAll`. 이 것은 개발자에게 일반적이고 기본적인 연산을 수행할 수 있는 간단한 방법을 제공할 것입니다. + +```js +const queryString = 'q=query+string+parameters'; +const withSpaces = queryString.replaceAll('+', ' '); +``` + +이 것은 또한 특수 정규식 문자를 이스케이핑 해야할 필요가 없습니다. (이스케이프 되지 않은 `'+'`을 확인하세요.) + +## 고차원 API + +제안된 시그니처는 현재 존재하는 `String.prototype.replace`와 동일합니다. + +```js +String.prototype.replaceAll(searchValue, replaceValue) +``` + +현재 TC39 합의에 따르면, `String.prototype.replaceAll`은 아래의 두 가지 경우만을 제외한 모든 경우에 `String.prototype.replace`와 동일하게 동작합니다. + +1. `searchValue`가 문자열일 경우, `String.prototype.replace`는 `searchValue`의 하나의 존재만을 대체하나, `String.prototype.replaceAll`는 (`.split(searchValue).join(replaceValue)`나 전역 & 적절히 이스케이프된 정규식의 사용과 같이)`searchValue`의 모든 존재를 대체합니다. +2. `searchValue` 비전역 정규식일 경우, `String.prototype.replace`는 단일 일치를 대체하나, `String.prototype.replaceAll`는 예외를 발생시킵니다. 이것은 ("모두 대체하지 마세요"라는 의미를 담고 있는) 전역 플래그의 결여와 ("모두 대체 하세요"라고 강력하게 제안하는) 호출되는 메서드의 이름 간의 내재된 혼란을 피하기 위함입니다. + +특히, `searchValue`가 전역 정규식일 경우, `String.prototype.replaceAll`는 `String.prototype.replace`와 동일하게 동작합니다. + + +## 다른 언어들과의 비교 + +* Java는 `CharSequence`를 받아 모든 존재를 대체하는 [`replace`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replace-java.lang.CharSequence-java.lang.CharSequence-) 를 가지고 있습니다. 또한 Java는 정규식을 (사용자가 특수 정규 문자를 사용하도록 요구된) 탐색 도구로 받아 기본적으로 모든 존재를 대체하는 [`replaceAll`](https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#replaceAll-java.lang.String-java.lang.String-) 를 가지고 있습니다. +* Python는 모든 존재를 대체하나, 대체할 수의 제한을 선택적 매개변수로 받는 [`replace`](https://www.tutorialspoint.com/python/string_replace.htm) 를 가지고 있습니다. +* PHP는 파이선과 동일하게 선택적 제한 매개변수를 가진 [`str_replace`](http://php.net/manual/en/function.str-replace.php) 를 가지고 있습니다. +* Ruby는 정규식이나 문자열 뿐 만 아니라 콜백 블록이나 일치 -> 대체 쌍의 해시를 받는 [`gsub`](https://ruby-doc.org/core/String.html#method-i-gsub) 를 가지고 있습니다. + +## 자주 묻는 질문들 + +### 주요 이점은 무엇인가요? + +공통적인 경우를 위한 단순화된 API는 정규식에 대한 지식을 요구하지 않습니다. 정규식 구문 문자를 이스케이프하지 않고 문자열을 전역으로 바꾸는 방법입니다. VM 측의 최적화 가능성이 개선될 수 있습니다. + +### 대신 `replace`에 `limit` 파라미터를 추가하는 것은 어떤가요? + +A: 이 것은 어색한 인터페이스 입니다. - 기본 제한은 1이기 때문에 사용자는 많은 존재가 있음을 알아야만 하거나, Infinity와 같은 것을 사용해야합니다. + +### `searchValue`이 빈 문자열이면 어떤 일이 발생하나요? + +`String.prototype.replaceAll`는 `String.prototype.replace`의 선례를 따릅니다. 모든 UCS-2/UTF-16 코드 단위 사이에 대체 값이 분할된 입력 문자열을 반환합니다. + +```js +'x'.replace('', '_'); +// → '_x' +'xxx'.replace(/(?:)/g, '_'); +// → '_x_x_x_' +'xxx'.replaceAll('', '_'); +// → '_x_x_x_' +``` + +## TC39 회의 기록 + +- [11월 2017](https://tc39.es/tc39-notes/2017-11_nov-28.html#10ih-stringprototypereplaceall-for-stage-1) +- [3월 2019](https://github.com/tc39/tc39-notes/blob/master/meetings/2019-03/mar-26.md#stringprototypereplaceall-for-stage-2) +- [7월 2019](https://github.com/tc39/tc39-notes/blob/master/meetings/2019-07/july-24.md#stringprototypereplaceall) +- [6월 2020](https://github.com/tc39/notes/blob/master/meetings/2020-06/june-2.md#stringprototypereplaceall-for-stage-4) + +## 명세서 + +- [Ecmarkup 소스](https://github.com/tc39/proposal-string-replaceall/blob/master/spec.html) +- [HTML 형식](https://tc39.es/proposal-string-replaceall/) + +## 구현 + +- [SpiderMonkey](https://bugzilla.mozilla.org/show_bug.cgi?id=1540021), [Firefox 77](https://bugzilla.mozilla.org/show_bug.cgi?id=1608168) 에 사용됨. +- [JavaScriptCore](https://bugs.webkit.org/show_bug.cgi?id=202471), [Safari 13.1](https://webkit.org/blog/10247/new-webkit-features-in-safari-13-1/#javascript-improvements) 에 사용됨. +- [V8](https://bugs.chromium.org/p/v8/issues/detail?id=9801), Chrome 85에 사용됨. +- 폴리필: + - [core-js](https://github.com/zloirock/core-js#stringreplaceall) + - [es-shims](https://github.com/es-shims/String.prototype.replaceAll) \ No newline at end of file From b711e98ebb70bfb52894bd72fbb808921d045240 Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Thu, 17 Aug 2023 14:17:24 +0900 Subject: [PATCH 22/22] =?UTF-8?q?ko=20:=20v-flag=20=EB=B2=88=EC=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/ko/proposal-regexp-v-flag.md | 403 +++++++++++++++++++++++++++++++ 1 file changed, 403 insertions(+) create mode 100644 src/ko/proposal-regexp-v-flag.md diff --git a/src/ko/proposal-regexp-v-flag.md b/src/ko/proposal-regexp-v-flag.md new file mode 100644 index 0000000..eb86502 --- /dev/null +++ b/src/ko/proposal-regexp-v-flag.md @@ -0,0 +1,403 @@ +# ECMAScript 제안서 : 문자열의 속성 + 집합 표기법과 정규표현식 `v` 플래그 + +## 저자 + +- Markus Scherer +- Mathias Bynens + +## 상태 + +이 제안서는 the 2023년 5월 16일 회의 동안 [the TC39 절차](https://tc39.es/process-document/)의 4단계에 도달하였습니다. 이 것은 2023년 6월 15일에 [the ECMAScript 사양](https://tc39.es/ecma262/)으로 [추가](https://github.com/tc39/ecma262/pull/2418)되어 the ECMAScript 2024 스냅샷에 포함될 예정입니다. + +2021년 5월 25일 TC39 회의를 기준으로, 이 제안은 공식적으로 [문자열 제안의 속성](https://github.com/tc39/proposal-regexp-unicode-sequence-properties)으로 가정합니다. + +## 요약 + +ECMAScript의 정규 문자 클래스에서는, 우리는 다음과 같은 집합 연산자들을 위한 문법과 어휘들을 추가하는 것을 제안합니다. + +- 차집합 / 뺄셈 (_A 중에서 B가 아닌 것_) +- 교집합 (_A에 포함되면서 B도 포함되는 것_) +- 중첩된 문자 클래스(_위의 연산을 가능하게 하기위해 필요한 것_) + +추가적으로, [문자열 속성의 제안](https://github.com/tc39/proposal-regexp-unicode-sequence-properties)에 추가됨으로써 문자열의 특정 유니코드 속성과 문자열 리터럴을 문자 클래스에 추가할 것을 제안합니다. + +이 제안서의 JavaScript 개발자를 위한 설명은 [v8.dev의 기능 기사를 참조하세요](https://v8.dev/features/regexp-v-flag). + +## 제안 동기 + +대부분의 정규 표현식 엔진은 수백 개의 범위가 필요하고 유니코드의 새 버전에 따라 변경될 수 있는 하드코딩 문자 클래스를 방지하기 위해 대부분 유니코드 문자 속성을 반영하는 명명된 문자 속성을 지원합니다. + +그러나 이러한 문자 속성은 시작점에 불과합니다. 일반적으로 덧셈(결합), 뺄셈(제외), "이것과 저것 모두"(교차)가 필요합니다. [UTS #18: 유니코드 정규 표현식](https://www.unicode.org/reports/tr18/#Subtraction_and_Intersection) 내의 집합 연산들을 지원하기 위한 권장사항을 확인해보세요. + +ECMA스크립트 정규식 패턴이 이미 제한된 형태로 하나의 집합 작업을 지원합니다. 이러한 클래스가 '\s' 또는 '\p{Decimal_Number}'와 같은 'CharacterClassEscape'인 경우, 문자들이나 범위, 클래스들의 집합을 만들 수 있습니다. + +특정한 집합 연산과 정규 표현식의 질문에 대한 웹 검색은 집합 연산들(몀명된 속성들의 장점을 잃음)이나 주장을 미리 확인(이러한 목적에 맞지않고 성능이 떨어짐) 로부터 발생하는 범위를 하드코딩하는 방식으로 나타납니다. + +우리는 중첩된 문자 클래스와 차집합과 교집합들을 위한 문법과 어휘들을 추가하는 것을 제안합니다. + +## 제안된 해결책 + +집합의 차이/뺄셈, 교집합, 중첩된 문자 클래스의 지원을 추가하기 위해 문자 클래스의 문법을 확장하는 것을 제안합니다. + +## 고수준 API + +정규 표현식 패턴 내에서 다음 기능을 제안합니다. + +``` +// 차집합 +[A--B] + +// 교집합 +[A&&B] + +// 중첩된 문자 클래스 +[A--[0-9]] +``` + +이러한 고차원 예제들을 통해 `A`와 `B`는 (`[a-z]`와 같은) 문자 클래스나 (`\p{ASCII}`와 같은) 속성 이스케이프, 어쩌면 (구체적인 논의에 따른) 단일 문자 또는 문자 범위의 자리 표시자로 간주됩니다. 조금 더 구체적인 실사용 사례는 [실질적인 예제 영역](#illustrative-examples)를 확인하세요. + +## 실질적인 예제 + +정규 문자 클래스와 유사한 문법 규칙을 구현한 ICU의 `UnicodeSet`를 사용한 실 사용 사례 입니다.(`[:POSIX syntax for properties:]`와 `UnicodeSet` 모두가 아닌 '\p{Perl for properties}'를 사용하도록 수정되었습니다.) + +- ASCII가 아닌 숫자를 ASCII 숫자로 변환하는 코드 + + ``` + [\p{Decimal_Number}--[0-9]] + ``` + +- 특정 스크립트의 "단어/식별자" 범위 탐색 + + ``` + [\p{Script=Khmer}&&[\p{Letter}\p{Mark}\p{Number}]] + ``` + +- "줄 바꿈 없는 공백" 탐색 + + ``` + [\p{White_Space}--\p{Line_Break=Glue}] + ``` + + ECMAScript는 현재 `\p{Line_Break=…}`를 지원하지 않습니다. 이 것은 단순히 예제입니다. + +- ASCII 문자를 제외한 이모지 문자 탐색 + + ``` + [\p{Emoji}--[#*0-9]] + + // …or… + + [\p{Emoji}--\p{ASCII}] + ``` + +- 비 스크립트인 특수 결합 표기 탐색 + + ``` + [\p{Nonspacing_Mark}&&[\p{Script=Inherited}\p{Script=Common}]] + ``` + +- ASCII 공간을 제외한 "보이지 않는 문자" 탐색 + + ``` + [[\p{Other}\p{Separator}\p{White_Space}\p{Default_Ignorable_Code_Point}]--\x20] + ``` + +- 다음으로 시작하는 "각 스크립트의 첫 글자" 탐색 + + ``` + [\P{NFC_Quick_Check=No}--\p{Script=Common}--\p{Script=Inherited}--\p{Script=Unknown}] + ``` + + ECMAScript는 현재 [`\p{NFC_Quick_Check=…}`](https://www.unicode.org/reports/tr15/#Quick_Check_Table)를 지원하지 않습니다. 이 것은 단순히 예제입니다. + +- 문자, 마크(문자 구분 기호) 또는 십진수인 모든 그리스 코드 포인트 탐색 + + ``` + [\p{Script_Extensions=Greek}&&[\p{Letter}\p{Mark}\p{Decimal_Number}]] + ``` + +- "Other" 'General_Category'를 제외하되, 후진 제어 문자를 추가한 모든 코드 포인트 탐색 + + ``` + [[\p{Any}--\p{Other}]\p{Control}] + ``` + +- 구분자를 제외한 할당된 모든 코드 포인트 탐색 + + ``` + [\p{Assigned}--\p{Separator}] + ``` + +- 할당되지 않은 코드 포인트는 제거하되, RTL 및 아라비아 문자 코드 포인트 탐색 + + ``` + [[\p{Bidi_Class=R}\p{Bidi_Class=AL}]--\p{Unassigned}] + ``` + + ECMAScript는 현재 [`\p{Bidi_Class=…}`](https://www.unicode.org/reports/tr44/#Bidi_Class)를 지원하지 않습니다. 이 것은 단순히 예제입니다. + + +- `General_Category` “Letter”이며 RTL 및 아라비아 문자 코드 포인트 탐색 + + ``` + [\p{Letter}&&[\p{Bidi_Class=R}\p{Bidi_Class=AL}]] + ``` + + ECMAScript는 현재 [`\p{Bidi_Class=…}`](https://www.unicode.org/reports/tr44/#Bidi_Class)를 지원하지 않습니다. 이 것은 단순히 예제입니다. + +- 형식 및 제어 문자(또는 동등하게 모든 대리, 개인 사용 및 할당되지 않은 코드 포인트)를 제외한 “Other” `General_Category` 내의 모든 문자 탐색 + + ``` + [\p{Other}--\p{Format}--\p{Control}] + ``` + +## 자주 묻는 질문들 + +### 새 문법이 이전 버전과 호환되나요? 다른 정규식 플래그가 필요한가요? + +이전 버전에 대한 호환성을 깨지 않는 것이 이 제안의 명시적인 목표입니다. 구체적으로, 우리는 현재 예외가 발생하지 않는 정규 표현식 패턴의 동작을 변경하고 싶지 않습니다. 새로운 문법이 사용 중임을 나타내는 어떤 방법이 필요합니다. + +우리는 네 개의 선택지를 고려하였습니다. + +- 표현식 외부에 자체적인 새로운 플래그 + +- 표현식 내부에 `L`은 하나의 ASCII 문자인 `(?L)` 형식의 지시자 + +- 현재 `u` 플래그(유니코드 모드)에서는 유효하지 않는 접두사 `\U…`. 하지만 `u` 플래그가 아닌 `\U`는 `U`와 동일하다는 것을 기억하세요. + - `u` 정규 표현식 내에서 알려지지 않는 이스케이프 문자열의 사용을 금지하는 것은 [의식적인 선택](https://web.archive.org/web/20141214085510/https://bugs.ecmascript.org/show_bug.cgi?id=3157) 이었습니다. 이는 확장의 종류를 가능하게 하였습니다. + +- _flag와 상관없이_ 존재하는 패턴들에서 유효하지 않은 [`(?[`](https://github.com/tc39/proposal-regexp-set-notation/issues/39)와 같은 접두사 + + +접두사를 사용하는 아이디어는 TC39 초기 회의에서 제안되었기 때문에, 우리는 다음과 같은 다양한 방식으로 작업하고 있었습니다. + +``` +UnicodeCharacterClass = '\UniSet{' ClassContents '}' +``` + +그러나 이 것은 개발자 친화적이지 않다는 것을 발견하였습니다. + +특히, 이 것은 접두사와 `u`플래그를 작성해야만 합니다. Waldemar는 전치사가 이것 만으로도 충분하게 보일 수 있고, 그러므로 개발자가 'u' 플래그를 추가하는 것을 생략하는 실수를 할 수 있다고 지적했습니다. 이러한 측면은 `u` 플래그를 사용하지 않고 현재 유효하지 않은 (`(?[`와 같은) 더 복잡한 전치사를 사용하여 해결할 수 있으나, 이는 가독성이 떨어지게 됩니다. + +또한 백슬래시 문자 접두사의 사용은 `{중괄호}`에 새로운 문법을 포함시킬 수 있습니다. (`\p{property}`, `\u{12345}`와 같은) 다른 특정 문법은 문자 클래스의 가장 바깥쪽 계층이 이상하게 보이므로 `[대괄호]` 대신 중괄호를 사용하기 때문입니다. + +마지막으로 식 내부에 여러 개의 새로운 문법 문자 클래스가 있는 경우 각 클래스에 접두사를 사용해야 하는데, 이는 투박합니다. + +표현식 내의 지시자는 매력적인 대안이지만, ECMAScript는 아직 이러한 지시자를 사용하지 않았습니다. + +따라서 새 플래그는 새 문자 클래스 문법을 나타내는 가장 간단하고 사용자 친화적이며 구문론적으로 가장 깨끗한 방법입니다. 이 것은 반드시 `u` 플래그를 암시하고 함께 사용되어야 합니다. + +`u`의 다음 문자인 `v` 플래그를 제안합니다. + +또한 [문자열의 속성](https://github.com/tc39/proposal-regexp-unicode-sequence-properties)에서 동일한 새로운 플래그를 사용하는 것을 제안합니다. + +즉, 새로운 플래그는 속성 및 문자 클래스와 관련된 몇 가지 연결된 변경 사항을 나타냅니다. + +- 문자열의 속성 +- 문자 클래스에 문자열 리터럴 또는 특정 속성을 통해 다중 문자 문자열 요소가 포함될 수 있습니다. +- 중첩된 클래스 +- 집합 연산자 +- 대괄호와 띄어쓰기의 단순한 파싱 +- [개선된 IgnoreCase 매칭](https://github.com/tc39/proposal-regexp-set-notation/issues/30) + +더 많은 의논을 위해서 [issue 2](https://github.com/tc39/proposal-regexp-set-notation/issues/2)를 확인하세요. + +### `v`플래그와 `u`플래그의 차이점이 무엇인가요? + +이 질문에 대한 답은 기존의 'u' RegExp를 'v'를 사용하도록 "업그레이드"할 때 유용할 수 있습니다. 차이점은 다음과 같습니다. + +1. (명백한 부분입니다.) 새로운 문법의 사용으로 만들어진 이전의 유효하지 않은 패턴들을 유효하게 할 수 있습니다. 예제는 다음과 같습니다. + + ``` + [\p{ASCII_Hex_Digit}--[Ff]] + \p{RGI_Emoji} + [_\q{a|bc|def}] + ``` +2. 이전의 특정 유효한 패턴들, 이스케이프되지 않은 [특정 문자](https://arai-a.github.io/ecma262-compare/snapshot.html?pr=2418#prod-ClassSetSyntaxCharacter) `(` `)` `[` `{` `}` `/` `-` `|` (`\` and `]`는 문자 클래스 내부에서 이스케이핑이 필요하지만, `u` 플래그에서는 항상 참입니다.) 또는 [두개의 구두점](https://arai-a.github.io/ecma262-compare/snapshot.html?pr=2418#prod-ClassSetReservedDoublePunctuator)를 포함한 경우 에러를 발생시킵니다. + + ``` + [(] + [)] + [[] + [{] + [}] + [/] + [-] + [|] + [&&] + [!!] + [##] + [$$] + [%%] + [**] + [++] + [,,] + [..] + [::] + [;;] + [<<] + [==] + [>>] + [??] + [@@] + [``] + [~~] + [^^^] + [_^^] + ``` + +3. `u` 플래그는 대소문자 구분 없이 매칭되는 동직으로 인해 어려움을 겪습니다. `v`플래그는 문법이 개선되었습니다. 자세한 사항은 [the explainer](https://v8.dev/features/regexp-v-flag#ignoreCase) 또는 [issue #30](https://github.com/tc39/proposal-regexp-set-notation/issues/30)을 확인하세요. + + +## 다른 정규식의 특징의 선례는 무엇인가요? + +몇몇 다른 정규식 엔진은 제안된 확장의 일부 또는 전부를 특정 형식으로 지원합니다. + +| 언어/구현사항 | 합집합 | 뺄셈 | 차집합 | 중첩된 클래스 | 문법적 차이 | +| -------------------------------------------------------------------------------------------------------------------------------------------- | ----- | ---------------- | ------------ | -------------- | -------------------- | +| [ICU regex](https://unicode-org.github.io/icu/userguide/strings/regexp.html#set-expressions-character-classes) | ✅ | ✅ | ✅ | ✅ | ❌ | +| [`java.util.regex.Pattern`](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/regex/Pattern.html) | ✅ | 🤷 \* | ✅ | ✅ | ❌ | +| [Perl (“experimental feature available starting in 5.18”)](https://perldoc.perl.org/perlrecharclass#Extended-Bracketed-Character-Classes) | ✅ | ✅ | ✅ | ✅ | ✅ | +| [.Net](https://docs.microsoft.com/en-us/dotnet/standard/base-types/character-classes-in-regular-expressions#CharacterClassSubtraction) | ✅ | ✅ | ❌ | ✅ | ❌ | +| [XML Schema](https://www.w3.org/TR/xmlschema-2/#charcter-classes) | ✅ | ✅ | ❌ | ✅ | ❌ | +| [Apache Xerces2 XPath regex](https://xerces.apache.org/xerces2-j/javadocs/xerces2/org/apache/xerces/impl/xpath/regex/RegularExpression.html) | ✅ | ✅ | ✅ | ✅ | ❌ | +| [Python regex module](https://pypi.org/project/regex/) (not built-in "re") | ✅ | ✅ | ✅ | ✅ | ✅ | +| [Ruby Regexp](https://docs.ruby-lang.org/en/2.0.0/Regexp.html#class-Regexp-label-Character+Classes) | ✅ | ❌ | ✅ | ❌ | ❌ | +| ECMAScript prior to this proposal | ✅ | ❌ | ❌ | ❌ | ❌ | +| ECMAScript with this proposal + +\* 뺄셈은 부정의 교집합으로서 [명시](https://docs.oracle.com/en/java/javase/15/docs/api/java.base/java/util/regex/Pattern.html#subtraction1)되었습니다. 오직 부정과 중첩된 클래스에 대한 지원으로 교집합과 차집합 `[^[^ab][^cd]] === [[ab]&&[cd]]` and `[^[^ab][cd]] === [[ab]--[cd]]`에 대한 함수적 동일성을 구현할 수 있습니다. 이것은 쉽게 읽혀지지 않습니다. 이러한 이유로, 우리의 제안은 교집합과 차집합에 대한 전용 구문도 포함합니다. + + +연산 순서와 같은 문법적인 차이점에 대한 레퍼런스는 아래와 같습니다. + +- [regular expression flavors that support character class subtraction](https://www.regular-expressions.info/charclasssubtract.html) +- [regular expression flavors that support character class intersection](https://www.regular-expressions.info/charclassintersect.html) + +특정 Stack Overflow 회의입니다. + +- [#3201689](https://stackoverflow.com/q/3201689/96656) +- [#10777728](https://stackoverflow.com/q/10777728/96656) +- [#15930181](https://stackoverflow.com/q/15930181/96656) +- [#17327765](https://stackoverflow.com/q/17327765/96656) +- [#29859968](https://stackoverflow.com/q/29859968/96656) +- [#44771741](https://stackoverflow.com/q/44771741/96656) +- [#55095497](https://stackoverflow.com/q/55095497/96656) + + +## 이 것은 순열 속성 제안으로 불리는 문자열 속성과 어떻게 상호작용을 하나요? + +2단계로 가는 과정에서 두 제안 사이의 상호작용을 설명하였습니다. (그 배경은 [issue #3](https://github.com/tc39/proposal-regexp-set-notation/issues/3)을 참고하세요.) + +새로운-구문-문자 클래스가 (클래스 내부에서 사용되는 문자열-속성이나 문자 리터럴로부터 오는)다중-문자-문자열 요소를 포함할 수 있도록 할 뿐만 아니라 문자열-속성을 가능하게 하기 위한 새로운 플래그가 필요하다는 것을 제안합니다. + +## 문자열 속성이 문자의 속성으로 변경될 수 있습니까, 아니면 그 반대입니까? + +단답으로는 아닙니다. + +길게 말하자면, 우리는 2019년 5월 유니코드 기술 위원회(UTC)에 이 문제를 제기하였고 ([L2/19-168](https://www.unicode.org/cgi-bin/GetMatchingDocs.pl?L2/19-168)와 [meeting notes](https://www.unicode.org/L2/L2019/19122.htm#:~:text=45-,B.13.8%20Supporting,Action%20Item%20for,-Mathias))를 참고하세요.) 이후(2021년 4월)에 구체적인 새로운 안정성 정책을 제안하였습니다. ([L2/21-091](https://www.unicode.org/cgi-bin/GetMatchingDocs.pl?L2/21-091)와 [meeting notes](https://www.unicode.org/L2/L2021/21066.htm#:~:text=D.2%20Stability,C11%5D%20Consensus)를 참고하세요.) +UTC는 우리의 제안을 승인하기로 합의하였습니다. 규범적이거나 정보적인 유니코드 속성의 도메인은 변경되지 않아야합니다. 특히 문자의 속성을 문자열의 속성으로 변경해서는 안되며, 그 반대의 경우도 마찬가지입니다. + + +## 속성 또는 문자열 클래스가 무한 문자열 집합과 일치할 수 있습니까? + +단답으로는 아닙니다. + +이 제안서는 단순히 [문자열 속성의 제안](https://github.com/tc39/proposal-regexp-unicode-sequence-properties)이며, 특정 문자열의 유한하고 명확한 문자열 집합(`Basic_Emoji`는 많은 단일 문자에 적용될 수 있습니다.)으로 확장되는 속성에 대한 지원을 추가합니다. 그리고 이 제안은 유한한 집합을 만드는 명시적으로 열거된 문자열을 가진 문자 클래스에 대한 구문을 추가합니다. 이것은 문자의 유한한 속성과 문자의 유한한 클래스/집합에서 자연스럽게 확장된 것입니다. + +예를 들어, UTS #51에서는 다음과 같은 매우 분명한 차이가 있습니다. + +1. 무한 문자열 집합과 일치하는 *정규식을 통해 정의된* [이모지 zwj 순열](https://www.unicode.org/reports/tr51/#def_emoji_zwj_sequence) +2. *데이터 파일에 나열된 문자열의 유한집합*인 (the RGI_Emoji_ZWJ_Sequence 속성과 동일한) [RGI 이모지 ZWJ 순열 집합](https://www.unicode.org/reports/tr51/#def_emoji_ZWJ_sequences) + +무한한 문자열 집합, 즉 일종의 명명된 하위-정규 표현식에 대해 명명된 일치에 대한 지원은 이론적으로 가능합니다. 이는 분명히 이 제안의 일부가 아니며, 그러한 가상 표현의 구문과 의미론에 대한 어떠한 추측도 이 제안의 일부가 아닙니다. + +향후 광범위한 확장을 가능하게 할 수 있는 예비 구문(중괄호와 같은)이 충분히 있지만, 제안된 사양 변경에 추가할 계획은 없습니다. + + +## 문자열이 포함된 문자 클래스의 일치 순서는 어떻게 됩니까? + +이 제안은 가장 긴 문자열이 가장먼저 일치되도록 보장합니다. 그래서 `'xy'`와 같은 접두사는 `'xyz'`와 같은 긴 문자열을 숨기지 않습니다. 예를 들어 `[a-c\q{W|xy|xyz}]` 패턴을 `'a'`, `'b'`, `'c'`, `'W'`, `'xy'`, 그리고`'xyz' 문자열에 대해 적용합니다. 이 패턴은 `xyz|xy|a|b|c|W`이나 `xyz|xy|[a-cW]`과 같이 동작합니다. + +가장 긴 문자열을 먼저 일치시키는 것은 `\p{RGI_Emoji}`와 같은 문자열 속성과의 통합에서 가장 중요합니다. 유니코드 속성은 수학적 의미의 문자/문자열 집합을 정의합니다. 그러므로 `[\p{RGI_Emoji}--\q{🇧🇪}]`와 같은 순서가 존재하지 않은 문자열에 대해 보존할 수 있는 문자열의 순서는 없습니다. + +가장 긴 문자열을 처음 일치하는 이론적 근거에 대한 자세한 내용은 [issue #25](https://github.com/tc39/proposal-regexp-set-notation/issues/25)를 확인하세요. + +문자 클래스에는 동일한 길이의 문자열이 여러 개 포함될 수 있습니다. `[xyz]`는 단일 문자로 구성된 3개의 문자열을 포함하며, (새로운 문자열 문법을 사용한) `[\q{xx|yy|zz}]`은 두 문자로 구성된 3개의 문자열을 포함합니다. 동일한 길이의 문자열에 대해 고유하거나 관찰 가능한 일치 순서가 없습니다. 위원회는 논의하였고 문자 클래스는 내재된 순서가 존재하지 않는 수학적 집합이라고 결론지었습니다. 마찬가지로, `[xyz]`와 `[zyx]` 사이의 명백한 일치 순서가 존재하지 않으며, `[\q{xx|yy|zz}]`와 `[\q{zz|yy|xx}]` 사이에도 일치 순서가 존재하지 않습니다. 이러한 뉘앙스는 구현자를 집합(수학적 집합의 구현)을 사용할 수 있도록 하며, 런타임 최적화를 시도합니다. + + +### 문자열의 속성이 원자성을 띄고 있나요? + +아니요. 이전의 FAQ에서 보았듯이 `\p{PropertyOfStrings}`는 단일성을 포함하는 [atomic group](https://www.regular-expressions.info/atomic.html)라기보다는 일반적인 단일성에서 분리됩니다. 이 동작은 다음과 같은 이유로 미래 지향적이라고 생각합니다. + +만약 분리된 제안의 일부로서 [atomic groups](https://github.com/rbuckton/proposal-regexp-atomic-operators)이 다른 언어의 통사적 선례를 따르는 ECMAScript에 추가된다면, 사용자가 다음과 같이 직접 선택할 수 있습니다. + +- 만약 원자성을 가진 동작을 원한다면, `(?>\p{PropertyOfStrings})`을 사용하세요. +- 먼역 원자성을 원하지 않는다면, `\p{PropertyOfStrings}`을 사용하세요. + +다른 한편으로 우리가 문자열의 속성의 원자성을 강요한다면, 다른 정규 표현식 종류에 새로운 "비원자" 정규식 연산자를 만드는 것 이외에는 원자성 동작에서 벗어날 수 있는 사용자의 선택은 없을 것입니다. + +자세한 것은 [issue #50](https://github.com/tc39/proposal-regexp-set-notation/issues/50)을 참고하세요. + + +## `B`가 `A`의 적절한 부분집합이 아닌 `A--B`의 경우에 차집합은 어떻게 작용합니까? + +이전 질문에 대한 답변에서 언급한 바와 같이, 현재의 ECMAScript 사양 및 다른 정규 표현식의 구현에 따라, **문자 클래스는 수학적 집합입니다.** 따라서, 기존 집합에 없는 문자열을 제거하는 것은 오류가 아니라 no-op입니다. `RGI_Emoji`에는 문자열 `🇧🇪`이 포함되지만 `RGI_Emoji_ZWJ_Sequence`에는 포함되지 않습니다. + +``` +# Proper subset. +[\p{RGI_Emoji}--\q{🇧🇪}] +# Not a proper subset. +[\p{RGI_Emoji_ZWJ_Sequence}--\q{🇧🇪}] +``` + +이러한 패턴 중 하나에 대한 예외가 발생한다면 혼란스럽고 역효과를 발생할 수 있습니다. + +[이 설명자의 실제 사례](https://github.com/tc39/proposal-regexp-set-notation#illustrative-examples) 중 일부 이 유용한 `A--B` 패턴을 사용하고 있으며, 우리가 지원하는 것은 매우 중요합니다. [배경에 대해서는 issue #32를 보세요.](https://github.com/tc39/proposal-regexp-set-notation/issues/32) + + +### 대칭차는 무엇입니까? + +대칭차에 대한 연산자를 제안하는 것 또한 고려하였습니다. ([issue #5](https://github.com/tc39/proposal-regexp-set-notation/issues/5)를 확인해보세요) 하지만, 좋은 사례를 발견하지 못했고 제한을 단순하게 유지하고자 하였습니다. + +그 대신, 추후 사용을 위해 쌍 ASCII 구두점과 기호를 예약할 것을 제안합니다. 이는 대칭차에 대한 [UTS \#18](https://www.unicode.org/reports/tr18/#Subtraction_and_Intersection)의 제안과 같이 `~~`를 추가하는 이후의 제안을 허용합니다. + + +### 이 제안이 ECMAScript 렉싱에 영향을 주나요? + +아니요. 이 제안 이전의 올바른 ECMAScript 렉서는 이 제안 이후에도 올바른 ECMAScript 렉서로 남는다는 것이 우리 제안의 명시적인 목표입니다. + +## TC39 회의록 및 슬라이드 + +- [11월 2020](https://github.com/tc39/notes/blob/master/meetings/2020-11/nov-18.md#adopting-unicode-behavior-for-set-notation-in-regular-expressions) ([slides](https://docs.google.com/presentation/d/1kroPvRuQ8DMt6v2XioFmFs23J1drOK7gjPc08owaQOU/edit)) +- [1월 2021](https://github.com/tc39/notes/blob/master/meetings/2021-01/jan-28.md#regexp-set-notation-for-stage-1) ([slides](https://docs.google.com/presentation/d/1vXlLpf3mEa_8Y-GDiRKLCqSzNXPOKWCF7tPb0H2M9hk/edit)) +- [3월 2021](https://github.com/tc39/notes/blob/master/meetings/2021-03/mar-10.md#regexp-set-notation-update) ([slides](https://docs.google.com/presentation/d/1dWEHdfSsWPwoln5RD2dwnBomIIytX20UFzYSnmRsIPY/edit)) +- [4월 2021 인큐베이터 호출](https://github.com/tc39/incubator-agendas/blob/master/notes/2021/04-08.md) ([slides](https://docs.google.com/presentation/d/1H2Doh8gbsRCthUoKCgFS-mTKxG2qY0vfC6D0dKvv4kc/edit)) +- [4월 2021](https://github.com/tc39/notes/blob/master/meetings/2021-04/apr-20.md#regexp-unicode-set-notation--properties-of-strings-update) ([slides](https://docs.google.com/presentation/d/1nV0NHUG5bd201rUSfJinLl8NTmnnyL5gTIhD0llsW1c/edit)) +- [5월 2021](https://github.com/tc39/notes/blob/master/meetings/2021-05/may-26.md#regexp-unicode-set-notation--properties-of-strings-for-stage-2) ([slides](https://docs.google.com/presentation/d/1nb_6ZcAjG4AKwVrwpalu1Ep-h7TONxoSm-uxKx83Wik/edit)) +- [8월 2021](https://github.com/tc39/notes/blob/master/meetings/2021-08/aug-31.md#regexp-set-notation--properties-of-strings) ([slides](https://docs.google.com/presentation/d/1foloLW13Elu0kslVsmD1hR_qZQBn8INcNpdWl0rlHrI/edit)) +- [12월 2021](https://github.com/tc39/notes/blob/master/meetings/2021-12/dec-14.md#regexp-set-notation--unicode-properties-of-strings-ready-for-stage-3-reviews) ([slides](https://docs.google.com/presentation/d/14AWHZvUeaKNHh_b_1xyqVlnDlYW8fWC4Lfgr0lHf2W4/edit)) +- [3월 2022](https://github.com/tc39/notes/blob/main/meetings/2022-03/mar-29.md#regexp-set-notation--unicode-properties-of-strings-for-stage-3) ([slides](https://docs.google.com/presentation/d/1_rcjmR2YLZMMB0i4SdZ4RV6eiJB7WmXo_i82_nh7vNg/edit)) +- [5월 2023](https://github.com/tc39/notes/blob/main/meetings/2023-05/may-16.md#regexp-v-flag-for-stage-4) ([slides](https://docs.google.com/presentation/d/1pjP06RhOAbYlh-6rYhe3v1SsxD2qLpiWAC2dKDBSJZo/edit)) + +## 사양 + +- [Ecmarkup source](https://github.com/tc39/ecma262/pull/2418) +- [HTML 버전](https://arai-a.github.io/ecma262-compare/?pr=2418) + +## 구현사항 + +- [SpiderMonkey/Firefox](https://bugzilla.mozilla.org/show_bug.cgi?id=1713657), shipping in Firefox 116 +- [V8/Chrome](https://bugs.chromium.org/p/v8/issues/detail?id=11935), enabled by default in V8 v11.2 / Chrome 112 (behind the `--harmony-regexp-unicode-sets` flag in earlier versions) +- [JavaScriptCore/Safari](https://bugs.webkit.org/show_bug.cgi?id=241593), enabled by default in [Safari Technology Preview 166](https://webkit.org/blog/13964/release-notes-for-safari-technology-preview-166/) & [Safari 17](https://webkit.org/blog/14205/news-from-wwdc23-webkit-features-in-safari-17-beta/) +- [Babel](https://babeljs.io/blog/2022/02/02/7.17.0) via [regexpu-core](https://github.com/mathiasbynens/regexpu-core) +- [ICU class UnicodeSet](https://unicode-org.github.io/icu/userguide/strings/unicodeset.html) can be built from a string with syntax like a regular expression character class. UnicodeSet has long supported set operations and multi-character strings, and recently ([in ICU 70](https://unicode-org.atlassian.net/browse/ICU-21652)) added support for emoji properties of strings. +- [C++ SRELL (`std::regex`-like library)](https://www.akenotsuki.com/misc/srell/en/#ecmascript_regexp) + + +[HTML `pattern` 속성에서의 `v`플래그](https://github.com/whatwg/html/pull/7908)에 대한 지원은 아래애서 가능합니다. + +- [Chrome 114](https://bugs.chromium.org/p/chromium/issues/detail?id=1412729) +- [Firefox 116](https://bugzilla.mozilla.org/show_bug.cgi?id=pattern-v) +- [Safari 17](https://bugs.webkit.org/show_bug.cgi?id=pattern-v) +