자바 스크립트 메타 프로그래밍을위한“Reflect”API 소개

이 강의에서는 ES2015 +에서 사용할 수있는 'Reflect'전역 개체에 대해 알아 보겠습니다. JavaScript 객체를 검사하고 수정할 수있는 다양한 정적 함수를 제공합니다.

(출처 : unsplash.com)

우리가 배운대로 이전 교훈 , 반사 대표 성찰 , 중재수정 프로그램을. ES2015 ( ES6 ) 이전에는 Object.keys또는 instanceof연산자 와 같은 프로그램의 동작을 조사하고 수정하는 데 사용할 수있는 몇 가지 도구가있었습니다 .

ES2015에서 우리는 메타 프로그래밍에 Reflect매우 유용한 방법 을 제공 하는 전역 개체를 받았습니다 . Like Mathand JSONobjects Reflect는 함수도 아니고 구성 할 수도 없습니다. 그것의 유일한 임무는 반사를위한 정적 방법을 제공하는 것입니다. 이러한 방법은 두 가지 범주로 나눌 수 있습니다.

Introspection 방법 은 비파괴 방법입니다. 개체를 검사하는 데만 사용됩니다. 수정 방법 은 객체 또는 그 동작을 변경하므로 파괴적입니다. 이러한 메서드의 대부분은 이전 JavaScript 구현 에서 파생 되었으며 이에 대해서도 설명합니다.

에서 이전 교훈 , 우리는 얼핏했다 Proxy절편 개체 작업에 사용되는 클래스를. Proxy 핸들러 메서드와 Reflect정적 메서드는 동일한 함수 서명을 공유합니다. 이에 대한 자세한 내용은 Proxy 강의 ( 곧 제공 예정 )에서 설명하지만 이러한 메서드 시그니처가 동일한 이유를 간략하게 설명하겠습니다. 이를 위해 ECMAScript 사양을 살펴볼 필요가 있습니다.

개체 내부 메서드 및 내부 슬롯

ECMAScript 2015 사양 의 6.1.7.2 섹션에서는 이상한 내부 속성과 내부 메서드 객체 (의 자손Object )가 가질 수있는 몇 가지에 대해 설명 합니다. 이러한 속성 또는 메서드는 JavaScript 엔진에 의해 구현되지만 런타임에서 추상화되므로 일반 속성과 같은 개체에서 액세스 할 수 없습니다.

이들은 내부 속성 또는 내부 메서드의 이름 인 [[<name>]]ECMAScript 사양 의 표기법 으로 표시됩니다 name. 이 주제에 대한 짧은 기사 ( 아래에 언급 됨 )를 작성했습니다.이 기사를 계속하기 전에 먼저 읽어보십시오.

Reflect의 정적 메서드 를 호출 할 때마다 일부 내부 메서드가 실행되거나 target결과를 반환하거나 target개체의 동작을 변경하는 개체에서 일부 내부 슬롯에 액세스합니다 . Proxy핸들러 메소드는 동일한 내부 메소드를 실행하므로 Proxy핸들러 메소드와 Reflect의 정적 메소드의 메소드 서명 이 동일합니다.

내성 방법

이러한 메서드는 순전히 내부 검사 목적으로 사용되며 개체, 동작 또는 내부 상태를 수정하지 않습니다.

● Reflect.get

Reflect.get(target, propertyKey[, receiver])

Reflect.get()호출은 유사 target[propertyKey]가의 프로토 타입의 속성 값을 검색으로 표현 target뿐만 아니라. 속성이 존재하지 않는 경우 target, undefined반환됩니다.

(reflect / get.js)

💡 당신은 또한 사용할 수 있습니다 Reflect.get(시 배열에 target입니다 Array)를를 사용하여 propertyKey는 AS number또는 string인덱스입니다.

이 방법은 내부 호출 [[Get]]하여 물체의 내부 방법 propertyKeyreceiver는 IS 대상에 target인수 [수신 REF ]. 따라서 비 객체 target( primitive value )가 제공되면이 메서드 호출은 TypeError예외 를 throw합니다 .

Reflect.get( null, 'prop' )
Reflect.get( 'hello', 'length' )
// TypeError: Reflect.get called on non-object

Reflect.has(target, propertyKey)
(reflect / has.js)

💡 당신은 또한 사용할 수 있습니다 Reflect.has(시 배열에 target입니다 Array)를를 사용하여 propertyKey는 AS number또는 string인덱스입니다.

이 메서드 는 인수 [ ref ] 에서 수신 된 대상에있는 [[HasProperty]]개체 의 내부 메서드를 내부적으로 호출합니다 . 따라서 비 객체 ( primitive value )가 제공되면이 메서드 호출은 예외 를 throw합니다 .propertyKeytargettargetTypeError

Reflect.has( null, 'prop' )
Reflect.has( 'hello', 'length' )
// TypeError: Reflect.has called on non-object

● Reflect.ownKeys

Reflect.ownKeys(target)
(reflect / ownKeys.js)

이 메서드 [[OwnPropertyKeys]]target[ ref ] 인수로 수신 된 대상에있는 객체 의 내부 메서드를 내부적으로 호출합니다 . 따라서 비 객체 target( primitive value )가 제공되면이 메서드 호출은 TypeError예외 를 throw합니다 .

Reflect.ownKeys( null )
Reflect.ownKeys( 'hello' )
// TypeError: Reflect.ownKeys called on non-object

Reflect.getOwnPropertyDescriptor(target, propertyKey)
(reflect / getOwnPropertyDescriptor.js)

💡 당신은 또한 사용할 수 있습니다 Reflect.getOwnPropertyDescriptor(시 배열에 target입니다 Array)를를 사용하여 propertyKey는 AS number또는 string인덱스입니다.

이 메서드 는 인수 [ ref ] 에서 수신 된 대상에있는 [[GetOwnProperty]]개체 의 내부 메서드를 내부적으로 호출합니다 . 따라서 비 객체 ( primitive value )가 제공되면이 메서드 호출은 예외 를 throw합니다 .propertyKeytargettargetTypeError

Reflect.getOwnPropertyDescriptor( null, 'prop' )
Reflect.getOwnPropertyDescriptor( 'hello', 'length' )
// TypeError: Reflect.getOwnPropertyDescriptor called on non-object

Object.getOwnPropertyDescriptor( null )
// TypeError: Cannot convert undefined or null to object
Object.getOwnPropertyDescriptor( 'hello', 'length' )
// {value: 5, writable: false, enumerable: false, …}
Object.getOwnPropertyDescriptor( {}, 'prop' )
// undefined

Reflect.getPrototypeOf(target)
(reflect / getPrototypeOf.js)

이 메서드 [[GetPrototypeOf]]target[ ref ] 인수로 수신 된 대상에있는 객체 의 내부 메서드를 내부적으로 호출합니다 . 따라서 비 객체 target( primitive value )가 제공되면이 메서드 호출은 TypeError예외 를 throw합니다 .

Reflect.getPrototypeOf( null )
Reflect.getPrototypeOf( 'hello' )
// TypeError: Reflect.getPrototypeOf called on non-object

Object.getPrototypeOf( null )
// TypeError: Cannot convert undefined or null to object
Object.getPrototypeOf( 'hello' )
// String {constructor: String(), anchor: ƒ, big: ƒ, …}
Object.getPrototypeOf( {} )
// Object {constructor: Object(), __defineGetter__: ƒ, …}

Reflect.isExtensible(target)
(reflect / isExtensible.js)

이 메서드는 개체에 새 속성을 추가하는 것을 방지하지만 개체에 대해 다른 작업을 수행 할 수 있습니다. 및 방법은 객체가 아닌 확장합니다.Object.preventExtenstions()Object.freeze()Object.seal()

이 메서드 [[IsExtensible]]target[ ref ] 인수로 수신 된 대상에있는 객체 의 내부 메서드를 내부적으로 호출합니다 . 따라서 비 객체 target( primitive value )가 제공되면이 메서드 호출은 TypeError예외 를 throw합니다 .

Reflect.isExtensible( null )
Reflect.isExtensible( 'hello' )
// TypeError: Reflect.isExtensible called on non-object

Object.isExtensible( null )
// false
Object.isExtensible( 'hello' )
// false
Object.isExtensible( {} )
// true

수정 방법

이러한 메서드는 target값이나 동작 또는 내부 상태를 수정합니다 .

● Reflect.deleteProperty

Reflect.deleteProperty(target, propertyKey)

delete연산자 와 마찬가지로 속성 propertyKey이 존재하지 않으면 항상을 반환 true합니다. 이 메서드는 target의 프로토 타입 체인 에있는 속성을 삭제하지 않으며 자신의 속성 만 삭제할 수 있습니다. 또한 구성 할 수없는 속성은 삭제할 수 없습니다.

(reflect / deleteProperty.js)

💡 당신은 또한 사용할 수 있습니다 Reflect.deleteProperty(시 배열에 target입니다 Array)를를 사용하여 propertyKey는 AS number또는 string인덱스입니다.

이 메서드 는 인수 [ ref ] 에서 수신 된 대상에있는 [[Delete]]개체 의 내부 메서드를 내부적으로 호출합니다 . 따라서 비 객체 ( primitive value )가 제공되면이 메서드 호출은 예외 를 throw합니다 .propertyKeytargettargetTypeError

Reflect.deleteProperty( null, 'prop' )
Reflect.deleteProperty( 'hello', 'length' )
// TypeError: Reflect.deleteProperty called on non-object

Reflect.set(target, propertyKey, value[, receiver])

속성이 이미 존재하고 thissetter 함수가있는 receiver경우 setter 함수 내부의 값은 제공 되는 경우가되고 그렇지 않으면 target사용됩니다. 이 방법은 표현식 을 사용하는 것과 같습니다 .target[propertyKey] = value

(reflect / set.js)

💡 당신은 또한 사용할 수 있습니다 Reflect.set(시 배열에 target입니다 Array)를를 사용하여 propertyKey는 AS number또는 string인덱스입니다.

이 방법은 내부 호출 [[Set]]와 대상물의 내부 방법 propertyKey, valuereceiver는 IS 대상에서 target인수받은 [ REF ]. 따라서 비 객체 target( primitive value )가 제공되면이 메서드 호출은 TypeError예외 를 throw합니다 .

Reflect.set( null, 'prop', 'val' )
Reflect.set( 'hello', 'length', 2 )
// TypeError: Reflect.set called on non-object

Reflect.defineProperty(target, propertyKey, descriptor)

속성이 이미 존재하는 경우 속성 설명 자만 업데이트됩니다. 에서 일부 속성 설명자 필드 만 제공된 descriptor경우 해당 필드 만 업데이트됩니다. 속성이 성공적으로 설정되면이 메서드는를 반환 true하고 그렇지 않으면 false반환됩니다.

(reflect / defineProperty.js)

💡 당신은 또한 사용할 수 있습니다 Reflect.defineProperty(시 배열에 target입니다 Array)를를 사용하여 propertyKey는 AS number또는 string인덱스입니다.

이 메서드 는 인수 [ ref ] 에서 수신 된 대상에 및 [[DefineOwnProperty]]이있는 개체 의 내부 메서드를 내부적으로 호출합니다 . 따라서 비 객체 ( primitive value )가 제공되면이 메서드 호출은 예외 를 throw합니다 .propertyKeydescriptortargettargetTypeError

Reflect.defineProperty( null, 'prop', {value: 2})
Reflect.defineProperty( 'hello', 'length', {value: 3})
// TypeError: Reflect.defineProperty called on non-object

● Reflect.preventExtensions

Reflect.preventExtensions(target)
(reflect / preventExtensions.js)

이 메서드 [[PreventExtensions]]target[ ref ] 인수로 수신 된 대상에있는 객체 의 내부 메서드를 내부적으로 호출합니다 . 따라서 비 객체 target( primitive value )가 제공되면이 메서드 호출은 TypeError예외 를 throw합니다 .

Reflect.preventExtensions( null )
Reflect.preventExtensions( 'hello' )
// TypeError: Reflect.preventExtensions called on non-object

Object.preventExtensions( null )
// false
Object.preventExtensions( 'hello' )
// 'hello'
Object.preventExtensions( {name: 'ross'} )
// {name: 'ross'}

Reflect.setPrototypeOf(target, prototype)

var obj = Object.preventExtensions({});
Reflect.setPrototypeOf(obj, null);
// false

Reflect.setPrototypeOf({}, "")
Reflect.setPrototypeOf(function(){}, "")
// TypeError: Object prototype may only be an Object or null
(reflect/setPrototypeOf.js)

Reflect.setPrototypeOf( null, null )
Reflect.setPrototypeOf( 'hello', null )
// TypeError: Reflect.setPrototypeOf called on non-object

Object.setPrototypeOf( null, null )
// TypeError: Object.setPrototypeOf called on null or undefined
Object.setPrototypeOf( Object.preventExtensions({}), null )
// ❌ TypeError: #<Object> is not extensible
Object.setPrototypeOf( {name: 'ross'}, "")
// TypeError: Object prototype may only be an Object or null
Object.setPrototypeOf( {name: 'ross'}, null )
// {name: 'ross'}

Reflect.apply(target, thisArgument, argumentsList)

이것은 호출하는 것과 apply의 프로토 타입 방법 target( (가) 경우 target함수이다 )하지만 몇 가지주의와. (가) 경우 argumentsList입니다 null거나 undefined, Reflect.apply던져 것 TypeError동안의 apply프로토 타입 방법은 인수없이 함수를 호출한다.

let func = ( ...args ) => console.log(args);
func.apply(null, undefined)
func.apply(null, null)
func.apply(null, {})
// []
func.apply(null, "")
// TypeError: CreateListFromArrayLike called on non-object
▶ func.apply(null, [1, 2, 3])
// [1, 2, 3]
Reflect.apply(func, null, undefined)
Reflect.apply(func, null, null)
Reflect.apply(func, null, "")
// TypeError: CreateListFromArrayLike called on non-object
Reflect.apply(func, null, {})
// []
▶ Reflect.apply(func, null, [1, 2, 3])
// [1, 2, 3]

Reflect.apply( null, null, [] )
// TypeError: Function.prototype.apply was called on null, which is a object and not a function
Reflect.apply( 'hello', null, [] )
// TypeError: Function.prototype.apply was called on hello, which is a string and not a function
Reflect.apply( {}, null, [] )
// TypeError: Function.prototype.apply was called on #<Object>, which is a object and not a function

Reflect.construct(target, argumentsList[, newTarget])

newTarget또한 그 생성자 함수 prototype새로 생성 된 인스턴스의 프로토 될 것이지만 그것이 사용하여 생성 될 target다음과 같이의 생성자 함수.

let instance = Object.create( newTarget.prototype )
target.apply( instance, argumentsList );

let instance = Object.create( target.prototype )
target.apply( instance, argumentsList );
(reflect/construct.js)

따라서 비 기능 또는 비 구성 요소 target가 제공되면이 메서드 호출은 TypeError예외 를 throw합니다 . 마찬가지로 프로토 타입이 newTarget있는 함수 ( 또는 클래스 )가 아닌 경우 a TypeError가 발생합니다.

Reflect.construct( {}, [] )
// TypeError: #<Object> is not a constructor
Reflect.construct( Symbol, [] )
// TypeError: Symbol is not a constructor
Reflect.construct( null, [] )
// TypeError: null is not a constructor
Reflect.construct( Object, [], Symbol )
// Symbol {}
Reflect.construct( Object, [], Reflect )
Reflect.construct( Object, [], Math )
Reflect.construct( Object, [], JSON )
// TypeError: #<Object> is not a constructor

대부분의 Reflect메서드는 some과 거의 같은 일을하지만 operators, 일부 정적 메서드 Object와 일부 프로토 타입 메서드는 Function우리가 본 것처럼합니다. 그러나의 시작 뒤에있는 주요 의제 Reflect반영을 위한 통합 API를 가져 오는 것이 었습니다 .

인스턴스 생성 또는 객체 속성 가져 오기, 설정 및 삭제와 같은 메서드 호출을 통해 모든 작업을 수행 할 수 있습니다. 언어가 성장함에 따라 복잡한 것을 단순화하기 위해 점점 더 많은 방법이 추가 될 것입니다.

Reflect다음 강의Proxy 에서 보게 될 강력한 도구 입니다.

(thatisuday.com / GitHub / Twitter / StackOverflow / Instagram)

Suggested posts

JavaScript : 사실, 부인 / 선생님 / 재판 ... 2 부

JavaScript : 사실, 부인 / 선생님 / 재판 ... 2 부

1 부에서는 기본적인 JavaScript 기본 사항을 다루기 시작했습니다. 이제 우리는 몇 가지 개념을 파헤 치고이 미친 일이 어떻게 작동하는지 더 잘 이해하려고 노력할 것입니다! 컬렉션은 데이터 컬렉션으로 구성된 객체 유형입니다. 배열,지도, 세트는 모두 객체에서 데이터를 수집하고 저장하는 다른 방법입니다.

성공적인 웹 프로젝트를 만드는 데 도움이 될 수있는 9 가지 팁

놓치고 싶지 않은 필수 팁.

성공적인 웹 프로젝트를 만드는 데 도움이 될 수있는 9 가지 팁

성공적인 웹 사이트를 구축하는 것은 매우 어렵습니다. 웹은 경쟁이 치열한 영역이며 통과해야합니다.

Related posts

성능 최적화 된 A / B 테스트 솔루션

성능 최적화 된 A / B 테스트 솔루션

의제 : 소개 : TL;하지만 읽을 수 있습니다. A / B 테스트, CloudFront 및 Lamba @ edge에 대해 이미 알고있는 경우 AWS Lambda @ edge를 사용한 A / B 테스트로 직접 이동하십시오. A / B 테스트 란 무엇입니까? A / B 테스트는 웹 사이트의 두 가지 버전에 대한 사용자의 참여를 비교하는 데 초점을 맞춘 UX 연구 방법론입니다.

fp-ts (Typescript)에서 Option 및 둘 중 하나 사용

저는 함수형 프로그래밍을 좋아합니다. 몇 년 동안 실수를하거나 토끼 구멍을 뚫는 것으로부터 저를 몇 번 구해 주었기 때문입니다. 동일한 입력이 주어지면 출력이 항상 동일하다는 것을 알면 안심입니다.

Syncfusion Blazor 파일 업로드 구성 요소에서 이미지를 미리 보는 방법

Syncfusion Blazor 파일 업로드 구성 요소에서 이미지를 미리 보는 방법

Syncfusion Blazor 파일 업로드는 하나 이상의 파일, 이미지, 문서, 오디오, 비디오 및 기타 파일을 서버에 업로드하기위한 구성 요소입니다. 여러 파일 선택, 진행률 표시 줄, 자동 업로드, 끌어서 놓기, 폴더 (디렉터리) 업로드, 파일을 포함하는 다양한 기능을 갖춘 HTML5 업로드 구성 요소 (<input type =”file”>)의 확장 버전입니다. 검증 등.

6 React 개발자로서 후회

내가 일찍했으면하는 것

6 React 개발자로서 후회

React는 배울 수있는 훌륭한 도구입니다. 그것은 우리가 우리 자신의 방식으로 일을 할 수있게합니다.