ECMAScript 6 (12): Proxy 와 Reflect
10638 단어 자바 script
Proxy 는 언어 차원 에서 수정 하 는 것 과 같은 기본 동작 을 수정 하 는 데 사 용 됩 니 다.그래서 프로 그래 밍 언어 를 프로 그래 밍 하 는 메타 프로 그래 밍 (meta programming) 에 속 합 니 다.프 록 시가 기본 동작 을 대리 한 것 으로 이해 된다.사용 형식 은 다음 과 같 습 니 다.
var proxy = new Proxy(target, handler);
target 은 대리 대상 이 고 handler 도 대상 입 니 다. 차단 행 위 를 맞 추고 내부 적 으로 모든 대리 행 위 를 정의 합 니 다.주의:
var proxy = new Proxy({},{
get: function(target, key){
return 35;
}
});
console.log(proxy.time); //35
console.log(proxy.name); //35
console.log(proxy.title); //35
// 35
실제로 proxy 대상 도 계승 할 수 있다.
var proxy = new Proxy({},{
get: function(target, key){
return 35;
}
});
var obj = Object.create(proxy);
obj.time = 20;
console.log(obj.time); //20
console.log(obj.name); //35
그 위력 을 느껴 보 자.
var obj = new Proxy({}, {
get: function(target, key, receiver){
console.log(`getting ${key} ...`);
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver){
console.log(`setting ${key} ...`);
return Reflect.set(target, key, value, receiver);
}
});
obj.count = 1; //setting count ...
++obj.count; //getting count ...
//setting count ...
console.log(obj.count); //getting count ...
//2
handler 대상 에서 get 방법 은 속성 을 나타 내 는 접근 요청, set 방법 은 속성 을 나타 내 는 기록 요청 을 알 수 있 습 니 다.물론 get 과 set 뿐만 아니 라 다음 차단 함 수 를 정의 할 수 있 습 니 다.
차단 대상 의 읽 기 속성.target 대상 이 propky 속성의 get 함 수 를 설정 할 때 receiver 는 get 함수 의 this 를 연결 합 니 다.반환 값 임 의
차단 대상 의 기록 속성.불 값 되 돌리 기
propkey in proxy 연산 자 를 차단 하고 불 값 을 되 돌려 줍 니 다.
delete proxy [propky] 연산 자 를 차단 하고 불 값 을 되 돌려 줍 니 다.
(let i in proxy) 스 트 리밍 기 를 차단 하고 스 트 리밍 기 를 되 돌려 줍 니 다.
proxy. hasOwnProperty (foo) 를 차단 하고 불 값 을 되 돌려 줍 니 다.
Object. getOwnProperty Names (proxy), Object. getOwnProperty Symbols (proxy), Object. keys (proxy) 를 차단 하고 배열 을 되 돌려 줍 니 다.이 방법 은 대상 의 모든 자체 속성 을 되 돌려 줍 니 다. 옮 겨 다 닐 수 없 는 속성 을 포함 하고 Symble 속성 은 포함 되 지 않 습 니 다. 단
Object.keys(proxy)
옮 겨 다 닐 수 없 는 속성 은 포함 되 어 서 는 안 됩 니 다.Object. getOwnPropertyDescriptor (proxy, propkey) 를 차단 하고 속성 설명 자 를 되 돌려 줍 니 다.
Object. defineProperty (proxy, propkey, propDesc), Object. defineProperties (proxy, propDesc) 를 차단 하고 불 값 을 되 돌려 줍 니 다.
Object. preventExtensions (proxy) 를 차단 하고 불 값 을 되 돌려 줍 니 다.
Object. getPrototypeOf (proxy) 를 차단 하고 대상 을 되 돌려 줍 니 다.
Object. isExtensible (proxy) 을 차단 하고 불 값 을 되 돌려 줍 니 다.
Object. setPrototypeOf (proxy, proto) 를 차단 하고 불 값 을 되 돌려 줍 니 다.
proxy 인 스 턴 스 를 차단 하 는 함수 작업 은 proxy (... args), proxy. call (object,... args), proxy. application (object, args) 을 포함 합 니 다.
new 로 proxy 함 수 를 호출 하 는 동작 을 차단 합 니 다. construct () 가 돌아 오 는 것 은 대상 이 아 닌 것 이 잘못 되 었 습 니 다.
다음은 프 록 시의 인 스 턴 스 를 열거 합 니 다.
방문 대상 이 존재 하지 않 는 속성 오류
var obj = new Proxy({}, {
get: function(target, key){
if(key in target){
return Reflect.get(target, key);
} else {
throw new ReferenceError(`"${key}" is not in object`);
}
}
});
obj.look = "picture";
console.log(obj.look); //"picture"
console.log(obj.sleep); //ReferenceError: "sleep" is not in object
배열 색인 이 마이너스 일 때 역수 위치의 값 을 되 돌려 줍 니 다.
var origin = [10,20];
var arr = new Proxy(origin, {
get(target, key){
let index = parseInt(key);
if(index < 0){
index = target.length + index;
if(index < 0) return undefined;
}
return Reflect.get(target, index);
}
});
console.log(arr[0]); //10
console.log(arr[1]); //20
console.log(arr[2]); //undefined
console.log(arr[-1]); //20
console.log(arr[-4]); //undefined
보호 대상 내 "" 로 시작 하 는 속성 은 사유 속성 입 니 다:
var o = {
"_name": "Bob",
"age": 13,
"_fun": function(){
console.log("_fun is called");
}
};
var obj = new Proxy(o, {
get(target, key){
if(key.charAt(0) === '_'){
return undefined;
}
return Reflect.get(target, key);
},
set(target, key, value){
if(key.charAt(0) === '_'){
throw new Error('Cannot define a property begin with "_"');
}
return Reflect.set(target, key, value);
},
has(target,key){
if(key.charAt(0) === '_'){
return false;
}
return Reflect.has(target, key);
},
deleteProperty(target,key){
if(key.charAt(0) === '_'){
return false;
} else {
Reflect.deleteProperty(..arguments);
}
},
apply(target,ctx,args){
if(target.name.charAt(0) === '_'){
throw new TypeError(`${target.name} is not defined`);
} else {
Reflect apply(...arguments);
}
},
defineProperty(target,key,desc){
if(key.charAt(0) === '_'){
return new Error(`cannot define property begin with "_"`);
} else {
Reflect.defineProperty(..arguments);
}
},
setPrototypeOf(target,proto){
throw new TypeError(`Cannot change the proto of ${target}`);
},
construct(target,ctx,args){
if(target.name.charAt(0) === '_'){
throw new TypeError(`${target.name} is not defined`);
} else {
Reflect construct(...arguments);
}
}
});
console.log(obj.age); //13
obj.age = 20;
console.log(obj.age); //20
console.log(obj._name); //undefined
obj._hobby = "Coding"; //Error: Cannot define a property begin with "_"
_name in key //false
delete obj._name;
Object.defineProperty(obj,"_hobby",{
value: "Coding"
});
Object.defineProperties(obj,{
'_hobby': {
value: "Coding"
}
});
obj._fun();
var a = new obj._fun();
obj.__proto__ = {}; //Cannot define a property begin with "_"
Object.setPrototypeOf(obj,{}) //Cannot change the proto of obj
물론 모든 proxy 프 록 시 프 록 시 를 취소 할 수 없 는 것 은 아 닙 니 다. 아래 방법 으로 설정 한 프 록 시 는 프 록 시 를 정의 할 때 되 돌아 오 는 revoke 함수 로 취소 할 수 있 습 니 다.
var a = {
name:"Bob"
};
var {proxy, revoke} = Proxy.revocable(a, {
get(target,key){
return undefined;
}
});
proxy.name; //undefined;
revoke();
proxy.name; //TypeError: Cannot perform 'get' on a proxy that has been revoked
반사 대상
Reflect 대상 은 다음 과 같은 역할 을 합 니 다.
Object.defineProperty
속성 을 정의 할 수 없 을 때 오 류 를 던 지고 Reflect.defineProperty
false Reflect.has(obj,name)
로 교체 name in obj
프 록 시 는 추가 기능 을 추가 할 때 Reflect 를 이용 하여 원시 기능 의 실현 을 보장 합 니 다.예 를 들 어:
var loggedObj = new Proxy({}, {
get(target,propKey){
console.log(`getting ${target}.${propKey}`); // log
return Reflect.get(target,propKey);
}
});
Reflect 는 다음 과 같은 방법 이 있 습 니 다.
같다
ObjectgetOwnPropertyDescriptor(target, propKey)
같다
Object.defineProperty(target,propKey,desc)
같다
Object.getOwnPropertyNames(target)
같다
Object.getPrototypeOf(target)
같다
Object.setPrototypeOf(target, proto)
같다
delete target.propKey
같다
for ... in target
같다
Object.freeze(target)
같다
Object.seal(target)
같다
Object.preventExtensions(target)
같다
Object.isFrozen(target)
같다
Object.isSealed(target)
같다
Object.isExtensible(target)
같다
propkey in object
같다
target.hasOwnProperty(propKey)
target 자체 의 모든 속성 을 두루 얻 을 수 있 습 니 다. 매 거 진 속성 을 포함 하고 Symbol 속성 은 포함 되 지 않 습 니 다.
propkey 가 리더 라면 리더 의 this 를 receiver 에 연결 합 니 다.
var per = {
bar: function(){console.log("per-bar")}
}
var obj = {
get foo(){ this.bar(); },
bar: function (){console.log("obj-bar")}
};
Reflect.get(obj, "foo", per); //"per-bar"
propkey 가 리더 라면 리더 의 this 를 receiver 에 연결 합 니 다.
Function.prototype.apply.call(target, thisArg, args)
즉 thisArg.target(args)
과 같다.같다
new target(...args)
상기 방법 중 Reflect.set()
, Reflect.defineProperty()
, Reflect.freeze()
, Reflect.seal()
, Reflect.preventExtensions()
성공 시 true 로 돌아 가 고 실패 시 false 로 돌아 갑 니 다.대응 하 는 Object 방법 이 실 패 했 을 때 오류 가 발생 합 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Thymeleaf 의 일반 양식 제출 과 AJAX 제출텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.