업데이트 2015 : 7th 의 답변 에서
지적했듯이 이제 ES6 (ECMAScript 2015)가 완성되었으므로 이제 더 적절한 문서를 사용할 수 있습니다.
원래 답변 ((역사적) 이해 및 추가 예) :
는 Reflection proposal
받는 진행 한 것으로 보인다 초안 인 ECMAScript 6 규격 . 이 문서는 현재 Reflect
-object의 메서드를 설명 하고 Reflect
-object 자체 에 대해 다음 사항 만 설명합니다 .
Reflect 객체는 단일 일반 객체입니다.
Reflect 객체의 [[Prototype]] 내부 슬롯 값은 표준 내장 Object 프로토 타입 객체 (19.1.3)입니다.
Reflect 객체는 함수 객체가 아닙니다. [[Construct]] 내부 메서드가 없습니다. new 연산자 를 사용하여 Reflect 객체를 생성자로 사용할 수 없습니다 . Reflect 객체에는 [[Call]] 내부 메서드도 없습니다. Reflect 객체를 함수로 호출 할 수 없습니다.
그러나 ES Harmony 의 목적에 대한 간단한 설명이 있습니다 .
"@reflect"모듈은 여러 용도로 사용됩니다.
- 이제 모듈이 있으므로 "@reflect"모듈은 이전에 Object에 정의 된 많은 리플렉션 메서드를위한보다 자연스러운 위치입니다. 이전 버전과의 호환성을 위해 Object의 정적 메서드가 사라질 가능성은 거의 없습니다. 그러나 새로운 메서드는 Object 생성자보다는 "@reflect"모듈에 추가되어야합니다.
- 글로벌 프록시 바인딩이 필요하지 않은 자연스러운 프록시 홈입니다.
- 이 모듈의 대부분의 메서드는 프록시 트랩에 일대일 매핑됩니다. 프록시 처리기는 아래와 같이 작업을 편리하게 전달하기 위해 이러한 메서드가 필요합니다.
따라서 Reflect
객체는 여러 유틸리티 기능을 제공하며, 그 중 많은 부분이 전역 객체에 정의 된 ES5 메서드와 겹치는 것처럼 보입니다.
그러나 이것이 해결하려는 기존 문제 또는 추가 된 기능을 설명하지는 않습니다. 나는 이것이 shimmed 될 수 있다고 생각했고 실제로 위의 조화 사양은 '이 방법의 비 규범 적이며 대략적인 구현'에 연결 됩니다.
그 코드를 검사하는 것은 (더) 아이디어는 그것의 사용에 대해,하지만 다행히도 위키는 또한이 줄 수있는 윤곽 객체가 유용 왜이 반영 가지 이유 :
(내가 복사 (그리고 포맷 한)과는 향후 참조를 위해 다음과 같은 텍스트 소스는 내가 찾을 수 있는 유일한 예이므로 이해가되며 이미 좋은 설명이 있고 질문의 apply
예를 터치합니다 .)
더 유용한 반환 값
대부분의 작업에서 Reflect
정의 ES5 작업과 유사하다 Object
등, Reflect.getOwnPropertyDescriptor
와 Reflect.defineProperty
. 그러나 Object.defineProperty(obj, name, desc)
will obj
속성이 성공적으로 정의되었을 때 반환 되거나 TypeError
그렇지 않으면 throw Reflect.defineProperty(obj, name, desc)
는 속성이 성공적으로 정의되었는지 여부를 나타내는 부울을 반환하도록 지정됩니다. 이를 통해이 코드를 리팩토링 할 수 있습니다.
try {
Object.defineProperty(obj, name, desc);
} catch (e) {
}
이에:
if (Reflect.defineProperty(obj, name, desc)) {
} else {
}
이러한 부울 성공 상태를 반환하는 다른 메서드는 Reflect.set
(속성 업데이트), Reflect.deleteProperty
(속성 삭제), Reflect.preventExtensions
(객체를 확장 불가능하게 만들기) 및 Reflect.setPrototypeOf
(객체의 프로토 타입 링크 업데이트)입니다.
일류 운영
ES5에서 객체 obj
가 특정 속성 이름을 정의하거나 상속 하는지 여부를 감지하는 방법 은 (name in obj)
. 마찬가지로 속성을 삭제하려면 delete obj[name]
. 전용 구문이 훌륭하고 짧지 만, 이는 또한 작업을 일류 값으로 전달하려는 경우 이러한 작업을 함수에 명시 적으로 래핑해야 함을 의미합니다.
하여 Reflect
이러한 작업이 용이 일류 함수로 정의된다
Reflect.has(obj, name)
의 기능적 동등 (name in obj)
과 Reflect.deleteProperty(obj, name)
같은 작업을 수행하는 기능이다delete obj[name].
보다 안정적인 기능 적용
ES5에서 f
배열로 압축 된 가변 개수의 인수를 사용 하여 함수를 호출 args
하고 this
값을에 바인딩하려면 다음과 같이 obj
작성할 수 있습니다.
f.apply(obj, args)
그러나 f
의도적으로 또는 의도하지 않게 자체 apply
메서드를 정의하는 개체 일 수 있습니다 . 내장 apply
함수가 호출 되었는지 확인하려면 일반적으로 다음과 같이 작성합니다.
Function.prototype.apply.call(f, obj, args)
이것은 장황 할뿐만 아니라 금방 이해하기 어려워집니다. 를 사용하면 Reflect
이제 더 짧고 이해하기 쉬운 방식으로 안정적인 함수 호출을 수행 할 수 있습니다.
Reflect.apply(f, obj, args)
가변 인수 생성자
가변 개수의 인수를 사용하여 생성자 함수를 호출한다고 가정 해보십시오. ES6에서는 새로운 확산 구문 덕분에 다음과 같은 코드를 작성할 수 있습니다.
var obj = new F(...args)
ES5에서, 하나는 사용할 수 있기 때문에 이것은 더 열심히 작성하는 것입니다 F.apply
또는 F.call
가변 인자를 가진 함수를 호출 할 수 있지만이 없습니다 F.construct
에 기능 new
가변 인자를 가진 함수는. 를 사용하면 Reflect
이제 ES5로 작성할 수 있습니다.
var obj = Reflect.construct(F, args)
프록시 트랩에 대한 기본 전달 동작
Proxy
개체를 사용하여 기존 개체를 래핑 할 때 작업을 가로 채고 작업을 수행 한 다음 일반적으로 가로 챈 작업을 래핑 된 개체에 적용하는 "기본 작업을 수행"하는 것이 매우 일반적입니다. 예를 들어 객체에 대한 모든 속성 액세스를 간단히 기록하고 싶다고 가정 해 보겠습니다 obj
.
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
}
});
Reflect
및 Proxy
API는 협력하여 설계된 각각 있도록, Proxy
함정, 해당 방법이 존재하는 Reflect
그 "기본 일을한다". 따라서 Proxy 핸들러 내에서 "기본"작업을 수행하려는 경우 항상 해당 Reflect
객체 에서 해당 메서드를 호출하는 것이 올바른 방법입니다 .
var loggedObj = new Proxy(obj, {
get: function(target, name) {
console.log("get", target, name);
return Reflect.get(target, name);
}
});
의 반환 형식 Reflect
방법의 반환 형식과 호환되도록 보장 Proxy
트랩.
접근 자의이 바인딩 제어
ES5에서는 일반 속성 액세스 또는 속성 업데이트를 수행하는 것이 매우 쉽습니다. 예를 들면 :
var name = ...
obj[name]
obj[name] = value
Reflect.get
및 Reflect.set
방법은 같은 일을하지만, 또한 마지막 옵션 인수로 받아 들일 수 있도록 receiver
명시 적으로 설정하는 방법을 수 있도록 매개 변수 this
속성이 당신이 얻을 때 - 결합을 / 세트는 접근이다 :
var name = ...
Reflect.get(obj, name, wrapper)
Reflect.set(obj, name, value, wrapper)
이것은 래핑 할 때 obj
접근 자 내에서 자체 전송이 래퍼로 다시 라우팅되기를 원할 때 유용합니다 ( 예 obj
: 다음과 같이 정의 된 경우 ).
var obj = {
get foo() { return this.bar(); },
bar: function() { ... }
}
전화 Reflect.get(obj, "foo", wrapper)
를 this.bar()
걸면 전화가로 다시 라우팅됩니다 wrapper
.
유산 피하기 __proto__
일부 브라우저에서는 __proto__
개체의 프로토 타입에 대한 액세스를 제공하는 특수 속성으로 정의됩니다. ES5 Object.getPrototypeOf(obj)
는 프로토 타입을 쿼리 하는 새로운 방법 을 표준화했습니다 . 객체의 프로토 타입을 설정 하는 데 해당하는를 정의 Reflect.getPrototypeOf(obj)
한다는 점을 제외하면 정확히 동일 Reflect
합니다 Reflect.setPrototypeOf(obj, newProto)
. 이것은 객체의 프로토 타입을 업데이트하는 새로운 ES6 호환 방법입니다.
참고 : setPrototypeOf
또한에 존재합니다Object
( Knu 의 의견에서 올바르게 지적한대로 )!
편집 :
사이드 노트 (Q에 대한 주석 처리) : 'Q : ES6 모듈 대 HTML 가져 오기' 에 대해 설명 Realms
하고 Loader
개체 를 설명 하는 짧고 간단한 답변이 있습니다.
이 링크에서 다른 설명이 제공됩니다 .
영역 개체는 고유 한 전역 개체, 표준 라이브러리의 복사본 및 "내장"(Object.prototype의 초기 값과 같이 전역 변수에 바인딩되지 않은 표준 개체)을 사용하여 고유 한 전역 환경의 개념을 추상화합니다.
확장 가능한 웹 : 이것은 <iframe>
DOM이없는 동일 출처의 동적 동등 물입니다
.
그래도 언급 할 가치 가 있습니다 .이 모든 것은 아직 초안이며 돌에 새겨 져있는 사양이 아닙니다! ES6이므로 브라우저 호환성을 염두에 두십시오!
도움이 되었기를 바랍니다!
Reflect
는Realm
및Loader
객체에 대한 컨테이너 일 뿐이지 만 후자가 무엇을하는지 모르겠습니다.