[JavaScript] Reflect

Narcoker·2023년 6월 15일
0

JavaScript

목록 보기
42/55
post-custom-banner

Reflect

Proxy의 trap과 동일한 메소드들 13개를 가지고 있다.
constructor 가 없어서 생성자 함수로 사용할 수 없다.
즉 new 를 사용할 수 없다.

Reflect.get()

target의 프로퍼티 값을 반환한다.

파라미터
target : 대상 오브젝트
key : 프로퍼티 식별자
receiver(선택) : this로 참조할 오브젝트

사용법 예제

const target = {
	point: 100,
    get getPoint(){
    	return this.point + 500;
    }
}
console.log(target.getPoint); // 600
console.log(Reflect.get(target, "getPoint");; // 600

const that = { point: 300 };
console.log(Reflect.get(target, "getPoint", that)); // 800

proxy 내부에 get 트랩이 있는 경우 that 파라미터를 무시한다.

const target = {
	point: 100,
    get getPoint(){
    	return this.point + 500;
    }
}
const handler ={
	get(target, key, receiver){
    	return target[key];
    }
};

const proxy = new Proxy(target, handler);
console.log(Reflect.get(proxy, "getPoint")); // 600
const that = {point: 200};
console.log(Reflect.get(proxy, "getPoint", that)); // 600, get 트랩이 있어서 that 무시

위 문제를 해결하기 위해서 get 트랩 내부에서 return 할때 Reflect.get() 으로 하면 된다.

const target = {
	point: 100,
    get getPoint(){
    	return this.point + 500;
    }
}
const handler ={
	get(target, key, receiver){
    	return Reflect.get(target, key, receiver); 
    }
};

const proxy = new Proxy(target, handler);
console.log(Reflect.get(proxy, "getPoint")); // 600
const that = {point: 200};
console.log(Reflect.get(proxy, "getPoint", that)); // 700, get 트랩 내부에서 Reflect 사용

Reflect.set()

target의 프로퍼티에 값을 할당한다.
프로퍼티가 없으면 만든다.

파라미터

target: 대상 오브젝트
key : 프로퍼티 key
value : 프로퍼티에 할당할 값
receiver(선택) : this 로 사용할 오브젝트

사용법 예제

Reflect.set()은 수행 성공 시 true 를 반환한다.

const target = {
	point: 100
};
console.log(target.point = 200); // 200
console.log(Reflect.set(target, "point", 300)); // true
console.log(target.point)); // 300

this로 참조할 오브젝트 작성

const target = {
	point: 100
    set setPoint(key){
    	target[key] = this.point + 500;
    }
};
target.setPoint = "point"; // set setPoint(key) 에서 key는 "point" 가 된다.
console.log(target.point); // 600

const that = { point: 300 };
Reflect.set(target, "setPoint", "point", that);
console.log(target.point); // 800

Proxy 핸들러의 set() 트랩 호출

const target = {
	point: 100
    set setPoint(key){
    	target[key] = this.point + 500;
    }
};
const handler = {
	set(target, key, value, receiver){
    	Reflect.set(target, key, value, receiver);
    }
};
const proxy = new Proxy(target, handler);
proxy.setPoint = "point"; // 트랩 호출
console.log(target.point); // 600

set() 트랩에서 this 참조 변경

const target = {
	point: 100
    set setPoint(key){
    	target[key] = this.point + 500;
    }
};
const handler = {
	set(target, key, value, receiver){
    	Reflect.set(target, key, value, receiver);
    }
};
const proxy = new Proxy(target, handler);
const that = { point : 300 }
Reflect.set(proxy, "setPoint", "point", that);
console.log(target.point); // 800

Reflect.has()

target의 key의 존재 여부를 반환한다.
상속받은 프로퍼티와 메서드도 검색한다.

존재하면 true 존재하지 않으면 false를 반환한다.

파라미터

target : 대상 오브젝트
key : 검색할 프로퍼티 식별자

사용법 예시

const target = {
	point: 100
};
console.log(Reflect.has(target,"point")); // true
console.log(Reflect.has(target. "hasOwnProperty")); // true

has() 트랩 호출

const target = {point: 100};
const handler = {
	has(target, key){
    	return Reflect.has(target, key);
    }
};
const proxy = new Proxy(target, handler);
console.log("point" in proxy);

Reflect.deleteProperty()

target에서 key를 삭제한다.

성공하면 true, 실패하면 false 를 반환한다.

파라미터

target : 대상 오브젝트
key : 검색할 프로퍼티 식별자

사용법 예시

const target = { point : 100 };
console.log(Reflect.deleteProperty(target, "point")); // true
console.log(Reflect.deleteProperty(target, "point")); // false

point의 프로퍼티 디스크립터 중 configurablefalse 이면 false를 반환한다.

const target = {};
Object.defineProperty(target, "point", {value: 100, configurable: false});
console.log(Reflect.deleteProperty(target, "point")); // false

인덱스로 배열 엘리먼트 삭제
1번 인덱스를 삭제하고 제한 인덱스의 엘리먼트에 undefined를 설정한다.
뒤의 인덱스들을 앞으로 당기지 않는다.

const target = [1,2,3,4];
Reflect.deleteProperty(target, 1);
console.log(target); // [1, undefind, 3, 4]

Reflect.defineProperty()

target에 프로퍼티를 추가, 변경한다.

성공 시 true, 실패시 false 를 반환한다.

파라미터

target: 대상 오브젝트
key: 프로퍼티 식별자
descriptor : 추가/변경할 디스크립터

사용법 예시

const target = {};
Reflect.defineProperty(target, "point", {value: 100, writable: true});

console.log(Object.getOwnPropertyDescriptor(target, "point", {value: 200})); // false
console.log(Reflect.get(target, "point"));
// {value: 100, writable: true, enumerable: false, configurable: false}

Reflect.preventExtensions()

target의 확장을 금지한다.

처리에 성공하면 true, 실패하면 false를 반환한다.

파라미터

target: 대상 오브젝트

사용법 예시

const target = {};
console.log(Refelct.preventExtensions(target)); // true
const result = Reflect.defineProerty(target, "point", {value: 100});
console.log(result); // false

Reflect.isExtensible()

target 프로퍼티 추가 가능 여부를 반환한다.

처리에 성공하면 true, 실패하면 false를 반환한다.

아래 함수를 실행한 상태라면 false를 반환한다.

  • Object.seal()
  • Object.freeze()
  • Object.preventExtensions()

파라미터

target: 대상 오브젝트

사용법 예시

const target = {point: 100};
console.log(Refelct.isExtensible(target)); // true
Reflect.preventExtensions(target); // 확장 금지

console.log(Refelct.isExtensible(target)); // false

Reflect.getPrototypeOf()

target.proto 를 반환한다. (상속을 해준 오브젝트)

파라미터

target: 대상 오브젝트

사용법 예시

let proto = Reflect.getPrototypeOf(Array);
console.log(proto === Function.prototype); // true
console.log(proto === Array.prototype); // false

const list = [];
proto = let proto = Reflect.getPrototypeOf(list);
console.log(proto == Array.prototype); // true

Reflect.setPrototypeOf()

target.__proto__을 재설정한다. = 부모 재설정

파라미터

target: 대상 오브젝트
prototype: 설정할 prototype 또는 null

사용법 예시

class Point{
	getPoint() { return 100; }
};
const target = function(){};
target.prototype.getPoint = function() { return 200; };

Reflect.setPrototypeOf(target, Point.Prototype);
console.log(target.getPoint()); // 100

Reflect.ownkeys()

target의 모든 프로퍼티 키를 배열로 반환한다.

상속받은 프로퍼티는 제외한다.

파라미터

target: 대상 오브젝트

사용법 예시

const sym = Symbol("심볼");
const target = {};
Object.defineProperties(target, {
	point: {value: 100, configurable: false}, // configurable 의미 없음
    [sym]: {value: 200}
});
Reflect.preventExtensions(target); // 의미 없음
console.log(Reflect.ownKeys(target)); // [point, Symbol(심볼)]
console.log(Object.keys(target)); // [], 모든 프로퍼티의 enumerable이 false 

Reflect.getOwnPropertyDescriptor()

target에서 프로퍼티 디스크립터를 반환한다.

상속받은 프로퍼티는 제외한다.

파라미터

target: 대상 오브젝트
key: 프로퍼티 식별자

사용법 예시

const target = {};
Object.defineProperties(target, {
	point: {value: 100, configurable: true} 
}
const desc = Reflect.getOwnPropertyDescriptor(target, "point");
console.log(desc); // {value: 100, writable: false, enumerable: true, ,configurable: true}

Reflect.contruct()

인스턴스를 생성하여 반환한다.

세번째 파라미터를 사용할 경우 생성된 인스턴스 타입은 세번째 파라미터 가 된다.

파라미터
target: 호출할 생성자 함수
[params] : 호출할 생성자 함수에 넘겨줄 파라미터
newTarget(선택) : target으로 생성한 인스턴스의 [[Prototype]] 즉 부모를 지정

사용법 예시

class Point{
	constructor(one, two) {
    	this.point = one + two;
    }
};

const obj = Reflect.construct(Point, [100,200])
console.log(obj.point); // 300
class Point{
	constructor(point) { this.point = point } 
    getPoint() {return this.point}
};
class Book {
	getTitle() {return "JS: " + this.point; }
};
const obj = Reflect.construct(Point, [100], Book);
console.log(obj instanceOf Point); // false
console.log(obj instanceOf Book); // true

console.log(obj.getPoint); // undefined
console.log(obj.getTitle); // JS: 100

class Point {
	constructor(...point){
    	this.point = point;
    }
    getPoint(){
    	return this.point;
    }
};
const handler = {
	construct(target, params, proxy){
    	return Reflect.construct(target, params);
    }
};
const proxy = new Proxy(Point, handler);
const obj = Reflect.construct(proxy, [1,2]); // 트랩 호출
console.log(obj.getPoint()); // [1,2]

Reflect.apply()

target에 작성한 함수를 호출한다.

파라미터

target: 작성한 함수
this: this로 사용할 오브젝트
params : target 함수에 넘겨줄 파라미터

사용법 예시

function add(..values){
	return values.map((value) => { // 만약 화살표 함수를 사용하지 않으면 this는 window가 된다.
    	return value + this.plus;
    });
};
console.log(Reflect.apply(add, {plus:100}, [1,2])); // [101, 102]

call(), apply() 통합

const indexOf = String.prototype.indexOf

console.log(indexOf.call("ABC", "B")); // 1
console.log(Reflect.apply(indexOf, "ABC", ["B"])); // 1

apply() 트랩 호출

function add(..values){
	return values.map((value) => { // 만약 화살표 함수를 사용하지 않으면 this는 window가 된다.
    	return value + this.plus;
    });
};

const handler = {
	apply(target, that, params){
    	return Reflect.apply(target, that, params);
    }
};
const obj = new Proxy(add, handler);
console.log(obj.apply({plus: 100}, [1,2])); // [101, 102]
profile
열정, 끈기, 집념의 Frontend Developer
post-custom-banner

0개의 댓글