머리말
ES6에서 프록시 생성자는 액세스 가능한 글로벌 객체이며,이를 사용하여 객체와 다양한 작동 객체의 동작 사이의 요청 된 작업에 대한 다양한 정보를 수집하고 원하는 모든 것을 반환 할 수 있습니다. ES6의 화살표 기능, 어레이 해체, REST 매개 변수 및 기타 기능은 구현되면 널리 순환되었지만 프록시와 같은 기능은 개발자가 거의 볼 수 없습니다. 한편으로는 브라우저 호환성 때문이며, 다른 한편으로는 개발자가 사용 시나리오를 깊이 이해해야하는 이러한 기능의 장점 때문입니다. 개인적으로, 나는 ES6의 프록시를 정말 좋아하기 때문에 간결하고 이해하기 쉬운 방식으로 객체에 대한 외부 액세스를 제어 할 수 있기 때문입니다. 다음에서 먼저 프록시가 사용되는 방법을 소개 한 다음 특정 예제를 나열하여 프록시의 사용 시나리오를 설명합니다.
프록시 , 이름과 의미를 참조하십시오. 설계 모드에서 프록시 모드와 매우 유사한 기능이 있으며, 이는 종종 세 가지 측면에서 사용됩니다.
1. 객체에 대한 외부 액세스를 모니터링합니다
2. 기능 또는 클래스 복잡성
3. 작업 전에 작업을 확인하거나 필요한 리소스를 관리하십시오.
프록시를 지원하는 브라우저 환경에서 프록시는 직접 사용할 수있는 전역 객체입니다. Proxy(target, handler) 는 생성자이며 target 기소되는 객체이며 handlder 다양한 프록시 작업을 선언하고 최종적으로 프록시 객체를 반환하는 객체입니다. 외부 세계가 프록시 객체를 통해 target 객체의 속성에 액세스 할 때마다 handler 객체를 통과합니다. 이 프로세스에서 프록시 객체는 미들웨어 (미들웨어)와 매우 유사합니다. 그렇다면 어떤 작업이 가로 채울 수 있습니까? 가장 일반적인 작업은 GET (읽기), 세트 (수정) 객체 속성 등입니다. 전체 차단 가능한 작업 목록을 보려면 여기를 클릭하십시오. 또한 프록시 객체는 언제든지 모든 프록시 작업을 로그 아웃 할 수있는 revoke 방법을 제공합니다. 공식적으로 프록시를 소개하기 전에 ES6에 추가 된 새로운 글로벌 객체 인 반사에 대한 특정 이해를 권장합니다.
기초적인
const target = {이름 : 'Billy Bob', Age : 15}; const handler = {get (target, key, proxy) {const today = new date (); console.log (`$ {key}에 $ {today}`)에 대한 요청을받은 요청; return reflect.get (대상, 키, 프록시); }}; const proxy = new proxy (target, handler); proxy.name; // => "2016 년 7 월 21 일 21 일에서 이름을 요청받은 요청 받기 15:26:20 GMT+0800 (CST)"// => "Billy Bob" 위의 코드에서 먼저 target 객체를 프록시 할 대상 객체를 정의 한 다음 모든 프록시 작업을 포함하는 handler 객체를 선언합니다. 다음으로 Proxy(target, handler) 사용하여 프록시 객체 proxy 만듭니다. 그 후 proxy 사용하여 target 속성에 대한 모든 액세스는 handler 에 의해 처리됩니다.
1. 검증 모듈을 종료하십시오
간단한 유형 확인부터 시작하겠습니다.이 유형의 데이터 유형의 정확성을 보장하기 위해 프록시를 사용하는 방법을 보여줍니다.
NumericDatastore = {count : 0, mold : 1234, total : 14}; numericdatastore = new proxy (numericdatastore, {set (target, key, value, proxy) {if (typeof value! = 'number') { "숫자 숫자의 속성"); }}); // "foo"가 숫자가 아니기 때문에 오류가 발생했습니다.객체의 모든 속성에 대한 검증자를 직접 개발하려면 프록시를 사용하여 코드 구조를 신속하게 구축 할 수 있으시면 검증기를 핵심 논리에서 분리하고 다음과 같이 나올 수 있습니다.
함수 createValidator (target, validator) {return new proxy (target, _validator : __validator : validator, set (target, key, value, proxy) {if (target.hasownproperty (key)) {this._validator [key]; if (!! validator (value)) {return.set (target, value, value, value, retain, value, proxy); $ {key}를 $ {value}로 설정합니다.} else {``$ {key}는 유효한 속성이 아닙니다}}}); }, age (val) {return typeof age === 'number'&& age> 18; }} 클래스 개인 {생성자 (이름, 나이) {this.name = 이름; this.age = age; CreateValidator를 반환합니다 (이, PersonValidators); }} const bill = new Person ( 'Bill', 25); // 다음 작업은 오류 Bill.name = 0; Bill.age = 'Bill'; Bill.age = 15; 체커와 메인 논리의 분리를 통해 관련 클래스 나 기능에 직접적인 손상을 일으키지 않고 personValidators 검증 자의 내용을 무한히 확장 할 수 있습니다. 더 복잡하기 위해 프록시를 사용하여 유형 검사를 시뮬레이션하여 기능이 올바른 유형 및 수량으로 매개 변수를 수신하는지 확인할 수 있습니다.
Obj = {pickymethodone : function (obj, str, num) { / *... * /}, pickymethodtwo : function (num, obj) { / *... * /}}; const argtypes = {pickymethodone : [ "대상", "문자열", "번호"], pickyMethodtwo : [ "obj = new", ","repy ","reving ","new "}; {target, key, proxy) {var value = argss = argchecker (key, argtypes [key]); 함수 ArgChecker (이름, Args, Checkers) {for (var idx = 0; idx <args.length; idx ++) {var arg = args [idx]; var type = checkers [idx]; if (! arg || typeof arg! == type) {console.warn (`$ {name}의 서명을 잘못 구현하고 있습니다. param $ {idx + 1}`); }}} obj.pickymethodone (); //> PickyMethodone의 서명을 잘못 구현하고 있습니다. ParkyMethodone의 서명을 잘못 구현하고 있습니다. Param 2 //> PickyMethodone의 서명을 잘못 구현하고 있습니다. param 3obj.pickymethodtwo ( "wopdapodoo", {}); //> PickyMethodone의 서명을 잘못 구현하고 있습니다. param 3obj.pickymethodtwo ( "wopdapodoo", {}); //> PickyMethodone의 서명을 잘못 구현하고 있습니다. param 3obj.pickymethodtwo ( "wopdapodoo", {}); //> PickyMethodtwo의 서명을 잘못 구현하고 있습니다. param 1 // 경고 없음 loggedobj.pickymethodone ({}, "작은 문자열", 123); obj.pickymethodone (123, {});2. 개인 속성
JavaScript 또는 기타 언어에서는 변수 이름 앞에 _ 추가하여 이것이 개인이 아닌 사유지 (실제로 개인이 아님)를 나타냅니다. 그러나 아무도 액세스하거나 수정하지 않을 것을 보장 할 수는 없습니다. 다음 코드에서는 api 객체 내부의 메소드 호출을 용이하게하기 위해 개인 apiKey 선언하지만 외부에서 api._apiKey 에 액세스 할 수 없습니다.
var api = {_apikey : '123abc456def',/ * this._apikey */ getUsers : function () {}, getUser : function (userId) {}, setUser : function (userId, config) {}}; // logs '123abc456def'; api._apikey); // 원하는 apikey = api._apikey로 _apikeys를 얻고 돌연변이합니다. api._apikey = '987654321';분명히,이 협약은 제한되지 않았습니다. ES6 프록시를 사용하여 실제 개인 변수를 구현할 수 있습니다. 다음은 다른 읽기 방법에 대한 두 가지 개인 방법을 보여줍니다.
첫 번째 방법은 SET/GET intercept 읽기 및 쓰기 요청을 사용하고 undefined:
api = {_apikey : '123abc456def', getUsers : function () {}, getUser : function (userId) {}, setUser : function (userId, config) {}}; const 제한 = [ '_apikey']; api = new proxy, {get (target, prox, get, key, get). if (restricted.indexof (key)> -1) {Throw Error (`$ {key}는 추가 정보를 참조하십시오. info.`); return recriber.get (대상, 키, 값, 프록시); // 다음 작업은 오류 콘솔을 던집니다.두 번째 방법은 사용중인 작업을 사용하는 것입니다.
var api = {_apikey : '123abc456def', getUsers : function () {}, getUser : function (userId) {}, setUser : function (userId, config) {}}; const 제한 = [ '_apikey']; api = new proxy (a key) (key) {rety) {rety). -1)? 거짓. has (target, key)}); //``iterators는 API의 "_ apikey"를 무시합니다. 프록시가 _apikey ... ")}을 가리기 때문에3. 액세스 로그
실행 환경에서 자주 호출하거나 천천히 실행하거나 더 많은 리소스를 취하는 속성 또는 인터페이스의 경우 개발자는 사용법이나 성능을 기록하려고합니다. 현재 프록시를 사용하여 미들웨어 역할을하고 로깅 기능을 쉽게 구현할 수 있습니다.
API = {_apikey : '123abc456def', getUsers : function () { / * ... * /}, getUser : function (userId) { / * ... * /}, setUser : setUser : function (userId, config) { / * ... * /}}; function logmethodync (timeStamp, method) {settoert (function) console.log (`$ {timeStamp} - 로깅 $ {method} 요청 비동기 적으로 요청합니다.}, 0)} api = new proxy (get : function, key, proxy) {var value = target [key]; return {retonments (returns) {returns () };}; api.getusers ();4. 조기 경고 및 차단
다른 개발자가 noDelete 속성을 삭제하는 것을 원하지 않고 oldMethod 에게 전화를 걸는 개발자 가이 방법이 포기되었음을 이해하거나 개발자에게 doNotChange 속성을 수정하지 말라고 지시 한 다음 Proxy를 사용하여이를 구현할 수 있다고 가정합니다.
DataStore = {Nodelete : 1235, OldMethod : function () {/*...*/}, donotchange : "true and true"}; const nodelete = [ 'nodelete']; const nochange = [ 'donotchange']; const imprecated = [ 'OldMethod']; datastore = new Proxy (datastore, {set (target, key, value, proxy) {if (nochange.includes (key)) {Throw Error (`error! $ {key}는 불변성입니다 .`);} return Recelf.set (target, key, value, proxy); {target, key (key)). 오류 (erry! $ {key}는 삭제할 수 없습니다. function (... args) {reflice.apply (target [key], target, args); val); DETATESTORE.NODELETE 삭제; DataStore.oldMethod ();5. 필터 작동
일부 작업은 큰 파일 전송과 같은 리소스를 매우 많이 차지합니다. 이 시점에서 파일이 이미 청크로 전송 된 경우 새 요청에 해당하는 (absolute)를 만들 필요가 없습니다. 현재 프록시를 사용하여 요청의 기능을 감지하고 응답 할 필요가없고 기능에 따라 응답 해야하는 기능을 필터링 할 수 있습니다. 다음 코드는 전체 코드가 아닌 기능을 필터하는 방법을 간략하게 보여줍니다. 나는 모두가 멋진 것들을 이해할 것이라고 믿는다.
OBJ = {getGiantFile : function (fileId) {/*...*/}}; obj = new proxy (get (target, key, proxy) {return function (... args) {const id = args [0]; isenroute = checkenroute (id); getcaced (id); (ISENROUTE || isdownloading) {Cached) {return repint.apply (target [key], target, args);6. 인터럽트 에이전트
프록시는 언제든지 target 에 대한 비산성을 지원하며, 종종 데이터 나 인터페이스에 대한 액세스를 완전히 둘러싸고 있습니다. 다음 예에서는 Proxy.revocable 메소드를 사용하여 프록시를 만들 수있는 프록시 객체를 만듭니다.
let sectivedata = {username : 'devbryce'}; const {infer {infectivedata, revokeaccess} = proxy.revocable (intitivedata, handler); function handlesSpectedHack () {rebkeaccess ();} // logs 'devbry'console.log (sementitavedata.username); handlesuspectedHack (); // typeError : RepokedConsole.log (intitivedata.username);데코레이터
ES7로 구현 된 데코레이터는 설계 모드의 데코레이터 모드와 같습니다. 프록시 및 데코레이터 의 사용 시나리오를 단순히 구별하는 경우 다음과 같이 요약 할 수 있습니다. 프록시의 핵심 기능은 외부 세계의 에이전트에 대한 액세스를 제어하는 것이며, 데코레이터의 핵심 기능은 데코레이터의 기능을 향상시키는 것입니다. 핵심 사용 시나리오에서 좋은 차이를 만드는 한 액세스 로그와 같은 기능이지만이 기사는 프록시 구현을 사용하지만 Decorator를 사용하여 구현할 수도 있습니다. 개발자는 프로젝트 요구, 팀 사양 및 자신의 선호도를 기준으로 자유롭게 선택할 수 있습니다.
요약
ES6의 프록시는 여전히 매우 실용적입니다. 겉보기에 간단한 기능은 크게 사용됩니다. ES6을 배우는 것이 도움이되기를 바랍니다.