From 3900c8899b2111dc8ecced8365ddc591ff1ded26 Mon Sep 17 00:00:00 2001 From: 1101707 Date: Wed, 15 Mar 2023 01:21:54 +0900 Subject: [PATCH 01/34] =?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/34] =?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/34] =?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/34] =?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/34] =?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/34] =?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/34] 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/34] =?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/34] 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/34] 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/34] 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/34] 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/34] 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/34] 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/34] 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/34] 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/34] 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/34] =?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/34] =?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/34] =?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 a72ea6e01409b1cb429484b263d2aee21b5368fd Mon Sep 17 00:00:00 2001 From: chanuuuuu Date: Thu, 18 May 2023 01:46:30 +0900 Subject: [PATCH 21/34] =?UTF-8?q?summary=20:=20proposal-global=20this=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-global.md | 96 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/ko/proposal-global.md diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md new file mode 100644 index 0000000..e850cef --- /dev/null +++ b/src/ko/proposal-global.md @@ -0,0 +1,96 @@ +# [globalThis](https://www.npmjs.com/package/globalthis) + +ECMAScript 제안서와 명세서, `globalThis`의 구현에 대해 담고 있습니다. + +[@ljharb](https://github.com/ljharb)가 해당 명세서에 대해서 초안을 작성하였습니다. + +이 제안서는 [과정](https://tc39.github.io/process-document/) 중, [4 단계](https://github.com/tc39/ecma262)에 있습니다. + +## 이론적 근거 +전역 객체에 대한 접근을 위한 간단한 ECMAScript 코드를 작성하는 것이 어렵습니다. 웹에서는 `window`나 `self`나 `this`, `frames`을 통하여 접근이 가능합니다. node.js에서 전역 객체는 `global`이나`this`으로 접근할 수 있습니다. 그 중에서도 `this`는 V8의 `d8`이나 JavaScriptCore의`jsc`과 같은 쉘에서만 사용이 가능합니다. 일반적으로 독립적인 함수를 호출하는 경우, `this`는 사용 가능하지만, 엄격 모드나, 모듈 내에서는 `undefined`를 가집니다. 이러한 방식으로, 전역 객체는 `Function('return this')()`를 통해서 접근이 가능합니다. 하지만 이러한 형식은 Chrome Apps 내부와 같은 몇몇의 CSP 설정에서는 접근이 불가능 합니다. 아래는 즉시 실행함수의 단일 인자로 전달되고 있는 전역객체를 접근하는 코드입니다. 이는 대부분의 경우에는 동작하지만 엄격 모드의 함수 내부이거나 모듈 내일 경우에는 `d8`에서 동작하지 않을 수 있습니다. (`Function` 트릭을 사용하면 고칠 수 있을 수도 있습니다.) + +```js +function foo() { + // 만약 브라우저인 경우, 전역 네임스페이스는 'window'라는 이름을 가집니다. 만약 node인 경우, 이름은 'global'입니다. + // 만약 쉘 안이라면, 'this'는 동작할 수 있습니다. + (typeof window !== "undefined" ? window : (typeof process === 'object' && typeof require === 'function' && typeof global === 'object') ? global : this); +} +``` + +추가적으로, `es6-shim` 은 [CSP 논의](https://github.com/paulmillr/es6-shim/issues/301)로 인해 `Function('return this')()`에서부터 변경이 필요하였습니다. 현재 브라우저들, node, 웹 워커들, 프레임들을 관리하기 위한 [변경점](https://github.com/paulmillr/es6-shim/commit/2367e0953edd01ae9a5628e1f47cf14b0377a7d6)은 아래와 같습니다. +```js +var getGlobal = function () { + // 전역객체에 접근할 수 있는 방법은`Function('return this')()`하나입니다. + // 그러나 이것은 Chrome 앱들에서는 CSP를 위반할 수 있습니다. + if (typeof self !== 'undefined') { return self; } + if (typeof window !== 'undefined') { return window; } + if (typeof global !== 'undefined') { return global; } + throw new Error('unable to locate global object');}; +``` + +## HTML 과 `WindowProxy` + +HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로운 속성은 `Window`에 선언되지만, 상위 단계인 `this`는 `WindowProxy`와 동일합니다. `WindowProxy`는 모든 객체 연산을 `Window`로 전달하지만, 페이지가 변경되면 `globalThis`는 유지되는 반면, `Windows`는 갱신됩니다. + +이러한 구분은 아래의 `parent.html`, `frame-a.html`, `frame-b.html`,파일들로 구성된 시나리오에서 확인할 수 있습니다. + +아래의 코드는 `frame-a.html` 입니다. +```html + +``` + +아래의 코드는 `frame-b.html`입니다. +```html + +``` + +아래의 코드는 `parent.html`’입니다. +```html + + +``` + +[이 데모](https://bead-pancake.glitch.me/)는 실제 전역객체 내에 네비게이션 동안 변경된 전역변수 `foo`가 저장되어있는 것을 보여줍니다. 하지만 `globalThis`는 네비게이션 동안 변경되지 않았습니다. 그러므로 `globalThis`는 전역객체가 아닙니다. + +따라서, `globalThis`는 JavaScript에서 직접적으로 접근할 수 없는 "전역객체"와 명백하게 다릅니다. [웹 브라우저에서는 `foo !== globalThis.foo`가 가능할 수도 있습니다.(전역 범위에서)](https://concise-walker.glitch.me/) + +ES6/ES2015는 `Window`/`WindowProxy` 구조를 설명하지 않으며, 단순히 "전역객체"라고 말하고 있습니다. 이 명세는 동일합니다. 만약 ECMAScript에서 top-level `this`가 `WindowProxy`로 설명되도록 명세가 변경된다면, 이러한 변경점은 해당 제안서에도 동일하게 반영되어야합니다. + +## SES interaction + +For Secure ECMAScript, it is important that all references to the global object be spoof-able and capable of being locked down, so that each context gets its own shadow global context. Additionally, references to the global object should not be reachable from other ECMAScript intrinsic objects, which SES would like to simply recursively freeze. In this proposal, `globalThis` is a writable and configurable property of the global object, so it should meet SES requirements. + +Secure ECMAScript에서는 전역객체에 대한 모든 참조가 스푸닝 가능하며, 잠길 수 있기 때문에 각 컨테스트가 숨겨진 전역 컨텍스트를 가질 수 있도록 하는 것이 중요합니다. 추가적으로, 전역객체에 대한 참조는 SES가 단순히 재귀적으로 동결하기를 원하는 다른 ECMAScript의 독립된 객체들에서 접근이 불가능해야합니다. 이 제안서에서 `globalThis`는 전역 객체의 쓰기 및 수정 가능한 속성입니다. 그러므로 이 것은 SES의 요구사항을 만족합니다. + + +## 네이밍 + +~~`System.global` 대신 기존 글로벌 속성 이름, 특히 `global` 또는 `window` 중 하나를 다시 정의하고자 하였습니다. 이 두 가지 중 하나가 런타임 환경 탐지를 수행하는 기존 코드를 중단하는지에 대한 추가 연구가 수행될 것입니다. 추가 연구를 통해 `global`을 사용해도 기존 코드가 깨지지 않을 것으로 확인되었습니다.~~ +`global`이라는 이름을 사용하려고 하였으나, 몇몇 웹사이트를 손상시키는 것으로 나타났습니다. + +데이터를 수집하여 몇몇 후보들의 웹 호환성을 확인한 후, 우리는 웹 호환성을 만족하면서 "전역 `this` 값"에 대한 개념에 대응되는 `globalThis`로 결정하였습니다. (그러면서도 [위의 개념](https://github.com/tc39/proposal-global#html-and-the-windowproxy)에 따라 “전역객체" 아닌). + +대체안들의 상세한 목록을 보기 위해서는 [NAMING.md](NAMING.md)을 확인하세요. + +## 명세서 +명세서를 [markdown format](spec.md) 또는 [HTML](http://tc39.github.io/proposal-global/)형식으로 볼 수 있습니다. + +## 감사 +최초로 영감을 주신 분은 https://twitter.com/littledan/status/627284720284372992 / http://littledan.github.io/global.html 입니다. From 3e4dccc90e3c8f33b96e5a751ba6637e4fa9346b Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:58:20 +0900 Subject: [PATCH 22/34] Update src/ko/proposal-global.md Co-authored-by: hochan Lee --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index e850cef..88f84b2 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -7,7 +7,7 @@ ECMAScript 제안서와 명세서, `globalThis`의 구현에 대해 담고 있 이 제안서는 [과정](https://tc39.github.io/process-document/) 중, [4 단계](https://github.com/tc39/ecma262)에 있습니다. ## 이론적 근거 -전역 객체에 대한 접근을 위한 간단한 ECMAScript 코드를 작성하는 것이 어렵습니다. 웹에서는 `window`나 `self`나 `this`, `frames`을 통하여 접근이 가능합니다. node.js에서 전역 객체는 `global`이나`this`으로 접근할 수 있습니다. 그 중에서도 `this`는 V8의 `d8`이나 JavaScriptCore의`jsc`과 같은 쉘에서만 사용이 가능합니다. 일반적으로 독립적인 함수를 호출하는 경우, `this`는 사용 가능하지만, 엄격 모드나, 모듈 내에서는 `undefined`를 가집니다. 이러한 방식으로, 전역 객체는 `Function('return this')()`를 통해서 접근이 가능합니다. 하지만 이러한 형식은 Chrome Apps 내부와 같은 몇몇의 CSP 설정에서는 접근이 불가능 합니다. 아래는 즉시 실행함수의 단일 인자로 전달되고 있는 전역객체를 접근하는 코드입니다. 이는 대부분의 경우에는 동작하지만 엄격 모드의 함수 내부이거나 모듈 내일 경우에는 `d8`에서 동작하지 않을 수 있습니다. (`Function` 트릭을 사용하면 고칠 수 있을 수도 있습니다.) +전역 객체에 접근하는 이식 가능한 ECMAScript 코드를 작성하는 것은 어렵습니다. 웹에서는 `window`, `self`, `this`나 `frames`로 접근할 수 있으며, node.js에서는 `global`이나`this`으로 접근할 수 있습니다. 그 중에서도 `this`는 V8의 `d8`이나 JavaScriptCore의`jsc`과 같은 쉘에서만 사용이 가능합니다. 일반적으로 sloppy 모드에서 독립적인 함수 호출에서 `this`는 사용 가능하지만, 엄격 모드나, 모듈 또는 함수 내에서는 `undefined`를 가집니다. 이러한 컨텍스트에서는 전역 객체는 `Function('return this')()`를 통해서 여전히 접근이 가능합니다. 하지만 이러한 형식은 Chrome Apps 내부와 같은 몇몇의 CSP 설정에서는 접근이 불가능 합니다. 아래는 즉시 실행 함수의 단일 인자로 전달되고 있는 전역객체를 접근하는 코드입니다. 이는 대부분의 경우에는 동작하지만 엄격 모드의 함수 내부이거나 모듈 내일 경우에는 `d8`에서 동작하지 않을 수 있습니다. (`Function` 트릭을 사용해서 해결할 수 있습니다.) ```js function foo() { From 1bbf5bc2ea9f5ea3926be3763c27f30124f80bea Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:58:32 +0900 Subject: [PATCH 23/34] Update src/ko/proposal-global.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 감사합니다. Co-authored-by: hochan Lee --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index 88f84b2..3f7063b 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -17,7 +17,7 @@ function foo() { } ``` -추가적으로, `es6-shim` 은 [CSP 논의](https://github.com/paulmillr/es6-shim/issues/301)로 인해 `Function('return this')()`에서부터 변경이 필요하였습니다. 현재 브라우저들, node, 웹 워커들, 프레임들을 관리하기 위한 [변경점](https://github.com/paulmillr/es6-shim/commit/2367e0953edd01ae9a5628e1f47cf14b0377a7d6)은 아래와 같습니다. +추가적으로, `es6-shim` 은 [CSP 논의](https://github.com/paulmillr/es6-shim/issues/301)로 인해 `Function('return this')()`에서부터 변경이 필요하였습니다. 브라우저들, node, 웹 워커들, 프레임들을 처리하기 위한 현재 [검사](https://github.com/paulmillr/es6-shim/commit/2367e0953edd01ae9a5628e1f47cf14b0377a7d6)는 아래와 같습니다. ```js var getGlobal = function () { // 전역객체에 접근할 수 있는 방법은`Function('return this')()`하나입니다. From 6590d75653f57f4ccfe954ed95a1f03e94cf990c Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:58:46 +0900 Subject: [PATCH 24/34] Update src/ko/proposal-global.md Co-authored-by: HyukJoo Kwon <76726411+huckjoo@users.noreply.github.com> --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index 3f7063b..a4d9654 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -30,7 +30,7 @@ var getGlobal = function () { ## HTML 과 `WindowProxy` -HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로운 속성은 `Window`에 선언되지만, 상위 단계인 `this`는 `WindowProxy`와 동일합니다. `WindowProxy`는 모든 객체 연산을 `Window`로 전달하지만, 페이지가 변경되면 `globalThis`는 유지되는 반면, `Windows`는 갱신됩니다. +HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로운 속성은 `Window`에 선언되지만, 상위 단계인 `this`는 `WindowProxy`와 동일합니다. `WindowProxy`는 모든 객체 연산을 `Window`로 전달하지만, 페이지가 변경되면 `globalThis`는 유지되는 반면, `Window`는 갱신됩니다. 이러한 구분은 아래의 `parent.html`, `frame-a.html`, `frame-b.html`,파일들로 구성된 시나리오에서 확인할 수 있습니다. From 65dac6b980cee8b99472ef121937b9ee6aa64856 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:58:56 +0900 Subject: [PATCH 25/34] Update src/ko/proposal-global.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-global.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index a4d9654..2f5c168 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -37,7 +37,9 @@ HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로 아래의 코드는 `frame-a.html` 입니다. ```html + globalThis.foo = 'a'; + globalThis.getGlobalThis = () => globalThis; + ``` 아래의 코드는 `frame-b.html`입니다. From 2b5b3c4bf03509a4c878cf6bbb27aa72de124020 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:59:02 +0900 Subject: [PATCH 26/34] Update src/ko/proposal-global.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index 2f5c168..f6f7415 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -32,7 +32,7 @@ var getGlobal = function () { HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로운 속성은 `Window`에 선언되지만, 상위 단계인 `this`는 `WindowProxy`와 동일합니다. `WindowProxy`는 모든 객체 연산을 `Window`로 전달하지만, 페이지가 변경되면 `globalThis`는 유지되는 반면, `Window`는 갱신됩니다. -이러한 구분은 아래의 `parent.html`, `frame-a.html`, `frame-b.html`,파일들로 구성된 시나리오에서 확인할 수 있습니다. +이러한 구분은 아래의 `parent.html`, `frame-a.html`, `frame-b.html` 파일들로 구성된 시나리오에서 확인할 수 있습니다. 아래의 코드는 `frame-a.html` 입니다. ```html From 87180295af813c2a27a746ee2ef1acd0659114ff Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:59:08 +0900 Subject: [PATCH 27/34] Update src/ko/proposal-global.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index f6f7415..47088b2 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -34,7 +34,7 @@ HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로 이러한 구분은 아래의 `parent.html`, `frame-a.html`, `frame-b.html` 파일들로 구성된 시나리오에서 확인할 수 있습니다. -아래의 코드는 `frame-a.html` 입니다. +아래의 코드는 `frame-a.html` 입니다. ```html + globalThis.getGlobalThis = () => globalThis; + ``` 아래의 코드는 `parent.html`’입니다. From 8d1f9bf53e696e6e56925f41e3a63f7bb603f740 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:59:23 +0900 Subject: [PATCH 29/34] Update src/ko/proposal-global.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index a4991f2..f83bcae 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -70,7 +70,7 @@ HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로 ``` -[이 데모](https://bead-pancake.glitch.me/)는 실제 전역객체 내에 네비게이션 동안 변경된 전역변수 `foo`가 저장되어있는 것을 보여줍니다. 하지만 `globalThis`는 네비게이션 동안 변경되지 않았습니다. 그러므로 `globalThis`는 전역객체가 아닙니다. +[이 데모](https://bead-pancake.glitch.me/)는 실제 전역객체 내에 탐색 중에 변경된 전역변수 `foo`가 저장되어있는 것을 보여줍니다. 하지만 `globalThis`는 탐색 중에 변경되지 않았습니다. 그러므로 `globalThis`는 전역객체가 아닙니다. 따라서, `globalThis`는 JavaScript에서 직접적으로 접근할 수 없는 "전역객체"와 명백하게 다릅니다. [웹 브라우저에서는 `foo !== globalThis.foo`가 가능할 수도 있습니다.(전역 범위에서)](https://concise-walker.glitch.me/) From e3dbb14a9e2ac1d5372fe29009792beb33fd73c6 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:59:29 +0900 Subject: [PATCH 30/34] Update src/ko/proposal-global.md Co-authored-by: hochan Lee --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index f83bcae..cecb860 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -72,7 +72,7 @@ HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로 [이 데모](https://bead-pancake.glitch.me/)는 실제 전역객체 내에 탐색 중에 변경된 전역변수 `foo`가 저장되어있는 것을 보여줍니다. 하지만 `globalThis`는 탐색 중에 변경되지 않았습니다. 그러므로 `globalThis`는 전역객체가 아닙니다. -따라서, `globalThis`는 JavaScript에서 직접적으로 접근할 수 없는 "전역객체"와 명백하게 다릅니다. [웹 브라우저에서는 `foo !== globalThis.foo`가 가능할 수도 있습니다.(전역 범위에서)](https://concise-walker.glitch.me/) +따라서, `globalThis`는 JavaScript에서 직접적으로 접근할 수 없는 "전역 객체"와 명백하게 다릅니다. [웹 브라우저에서는 (심지어 전역 범위에서도) `foo !== globalThis.foo`가 가능할 수도 있습니다.](https://concise-walker.glitch.me/) ES6/ES2015는 `Window`/`WindowProxy` 구조를 설명하지 않으며, 단순히 "전역객체"라고 말하고 있습니다. 이 명세는 동일합니다. 만약 ECMAScript에서 top-level `this`가 `WindowProxy`로 설명되도록 명세가 변경된다면, 이러한 변경점은 해당 제안서에도 동일하게 반영되어야합니다. From b7e46ab3d2ea86e7a238c0363d2e412399065d5e Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:59:36 +0900 Subject: [PATCH 31/34] Update src/ko/proposal-global.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index cecb860..7289d78 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -74,7 +74,7 @@ HTML에서 전역객체는 `Window`와 `WindowProxy`로 구별됩니다. 새로 따라서, `globalThis`는 JavaScript에서 직접적으로 접근할 수 없는 "전역 객체"와 명백하게 다릅니다. [웹 브라우저에서는 (심지어 전역 범위에서도) `foo !== globalThis.foo`가 가능할 수도 있습니다.](https://concise-walker.glitch.me/) -ES6/ES2015는 `Window`/`WindowProxy` 구조를 설명하지 않으며, 단순히 "전역객체"라고 말하고 있습니다. 이 명세는 동일합니다. 만약 ECMAScript에서 top-level `this`가 `WindowProxy`로 설명되도록 명세가 변경된다면, 이러한 변경점은 해당 제안서에도 동일하게 반영되어야합니다. +ES6/ES2015는 `Window`/`WindowProxy` 구조를 설명하지 않으며, 단순히 "전역객체"라고 말하고 있습니다. 이 명세는 동일합니다. 만약 ECMAScript에서 top-level `this`가 `WindowProxy`로 설명되도록 명세가 변경된다면, 이러한 변경점은 해당 제안서에도 동일하게 반영되어야 합니다. ## SES interaction From 6de8f75f70b60a29c5486689e5bb98094b05d403 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:59:42 +0900 Subject: [PATCH 32/34] Update src/ko/proposal-global.md Co-authored-by: Dami Kim <56783350+damilog@users.noreply.github.com> --- src/ko/proposal-global.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index 7289d78..03226e0 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -78,7 +78,6 @@ ES6/ES2015는 `Window`/`WindowProxy` 구조를 설명하지 않으며, 단순히 ## SES interaction -For Secure ECMAScript, it is important that all references to the global object be spoof-able and capable of being locked down, so that each context gets its own shadow global context. Additionally, references to the global object should not be reachable from other ECMAScript intrinsic objects, which SES would like to simply recursively freeze. In this proposal, `globalThis` is a writable and configurable property of the global object, so it should meet SES requirements. Secure ECMAScript에서는 전역객체에 대한 모든 참조가 스푸닝 가능하며, 잠길 수 있기 때문에 각 컨테스트가 숨겨진 전역 컨텍스트를 가질 수 있도록 하는 것이 중요합니다. 추가적으로, 전역객체에 대한 참조는 SES가 단순히 재귀적으로 동결하기를 원하는 다른 ECMAScript의 독립된 객체들에서 접근이 불가능해야합니다. 이 제안서에서 `globalThis`는 전역 객체의 쓰기 및 수정 가능한 속성입니다. 그러므로 이 것은 SES의 요구사항을 만족합니다. From 06f175fade402bef7ab6b69adb76b7e671d5932d Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:59:48 +0900 Subject: [PATCH 33/34] Update src/ko/proposal-global.md Co-authored-by: hochan Lee --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index 03226e0..a1467a0 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -79,7 +79,7 @@ ES6/ES2015는 `Window`/`WindowProxy` 구조를 설명하지 않으며, 단순히 ## SES interaction -Secure ECMAScript에서는 전역객체에 대한 모든 참조가 스푸닝 가능하며, 잠길 수 있기 때문에 각 컨테스트가 숨겨진 전역 컨텍스트를 가질 수 있도록 하는 것이 중요합니다. 추가적으로, 전역객체에 대한 참조는 SES가 단순히 재귀적으로 동결하기를 원하는 다른 ECMAScript의 독립된 객체들에서 접근이 불가능해야합니다. 이 제안서에서 `globalThis`는 전역 객체의 쓰기 및 수정 가능한 속성입니다. 그러므로 이 것은 SES의 요구사항을 만족합니다. +Secure ECMAScript에서는 전역 객체에 대한 모든 참조가 스푸닝 가능하며, 잠길 수 있기 때문에 각 컨테스트가 숨겨진 전역 컨텍스트를 가질 수 있도록 하는 것이 중요합니다. 추가적으로, 전역 객체에 대한 참조는 SES가 단순히 재귀적으로 동결하기를 원하는 다른 ECMAScript의 내제 객체에서 접근이 불가능해야합니다. 이 제안서에서 `globalThis`는 전역 객체의 쓰기 및 구성 가능한 속성이므로, SES의 요구 사항을 충족해야 합니다. ## 네이밍 From 668ce9d8ce54a01897061042b65e017accc17262 Mon Sep 17 00:00:00 2001 From: Chanwoo Park <42171155+chanuuuuu@users.noreply.github.com> Date: Wed, 21 Jun 2023 23:59:52 +0900 Subject: [PATCH 34/34] Update src/ko/proposal-global.md Co-authored-by: hochan Lee --- src/ko/proposal-global.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ko/proposal-global.md b/src/ko/proposal-global.md index a1467a0..21f5e90 100644 --- a/src/ko/proposal-global.md +++ b/src/ko/proposal-global.md @@ -84,7 +84,7 @@ Secure ECMAScript에서는 전역 객체에 대한 모든 참조가 스푸닝 ## 네이밍 -~~`System.global` 대신 기존 글로벌 속성 이름, 특히 `global` 또는 `window` 중 하나를 다시 정의하고자 하였습니다. 이 두 가지 중 하나가 런타임 환경 탐지를 수행하는 기존 코드를 중단하는지에 대한 추가 연구가 수행될 것입니다. 추가 연구를 통해 `global`을 사용해도 기존 코드가 깨지지 않을 것으로 확인되었습니다.~~ +~~`System.global` 대신 기존 전역 속성 이름, 특히 `global` 또는 `window` 중 하나를 다시 정의하고자 하였습니다. 이 두 가지 중 하나가 런타임 환경 탐지를 수행하는 기존 코드를 중단하는지에 대한 추가 연구가 수행될 것입니다. 추가 연구를 통해 `global`을 사용해도 기존 코드가 깨지지 않을 것으로 확인되었습니다.~~ `global`이라는 이름을 사용하려고 하였으나, 몇몇 웹사이트를 손상시키는 것으로 나타났습니다. 데이터를 수집하여 몇몇 후보들의 웹 호환성을 확인한 후, 우리는 웹 호환성을 만족하면서 "전역 `this` 값"에 대한 개념에 대응되는 `globalThis`로 결정하였습니다. (그러면서도 [위의 개념](https://github.com/tc39/proposal-global#html-and-the-windowproxy)에 따라 “전역객체" 아닌).