소개를 반영하십시오 :
반사 객체는 내 노드 (v4.4.3)에서 구현되지 않았으며 Babel (6.7.7)은 구현되지 않았습니다. 크롬의 새 버전이 지원됩니다. FF는 프록시를 지원하고 오랫동안 반영했습니다. 노드가 반사를 지원하려면 하모니 반사를 설치할 수 있습니다.
반사는 생성자가 아닙니다. 사용하면 Reflect.Method ()을 통해 직접 호출됩니다. 일부 반영 방법은 프록시와 유사하며 대부분의 반사 방법은 기본 객체가 다시 구현되었습니다.
반사를 사용해야합니다
반사가 사용되는 몇 가지 이유는 다음과 같습니다. 번역 주소 : 반사, 대략 번역 :
1 : 더 유용한 반환 값 : Reflect : ES5의 객체 메소드와 같은 몇 가지 메소드가 있습니다. : recil.getOwnPropertyDescriptor 및 Reflect.DefineProperty. 그러나 Object.DefineProperty (obj, name, desc)가 성공적으로 실행되면 OBJ와 다른 이유로 인한 다른 오류가 반환됩니다. 반사 .DefineProperty는 오브젝트의 속성이 설정되었는지 여부를 표시하기 위해 False 또는 True 만 반환합니다. 다음 코드는 리팩토링 될 수 있습니다.
{object.defineProperty (obj, name, desc); // 속성이 성공적으로 정의 된 속성} catch (e) {// 가능한 실패 (실수로 잘못된 예외를 포착 할 수 있음)} try}}}다음과 같이 재구성되었습니다.
if (recriber.defineProperty (obj, name, desc)) {// success} else {// failure}Relect.set, Reflect.deleteProperty, Reflect.preventextensions, recil.setPrototypof와 같은 다른 방법은 모두 리팩토링 될 수 있습니다.
2 : 기능 작동. OBJ에 정의가 정의되거나 속성 이름을 상속하는지 확인하려면 다음과 같이 ES5에서 판단 할 수 있습니다. OBJ의 이름;
또는 속성 삭제 : OBJ [이름]을 삭제합니다. 이것들은 매우 유용하고 매우 짧고 명확하지만, 사용될 때도 수업에 캡슐화되어야합니다.
반사를 사용하면 캡슐화, 반사 (obj, name), reclic.deleteproperty (obj, name);
3 :보다 신뢰할 수있는 기능 실행 방법 : ES에서는 함수 f를 실행하고 매개 변수 세트를 전달하려면 args를 묶고 바인딩하면 다음을 작성해야합니다.
f.apply (obj, args)
그러나 F 응용 프로그램은 사용자 자체 애플리케이션으로 재정의 될 수 있으므로이 방법을 작성하는 것이 더 신뢰할 수 있습니다.
function.prototype.apply.call (f, obj, args)
위의 코드는 너무 길고 이해하기 어렵습니다. 반사를 통해 우리는 더 짧고 간결하고 명확 할 수 있습니다.
반사. Apply (f, obj, args)
4 : 변수 매개 변수 형식의 생성자 : 불확실한 길이의 매개 변수를 통해 생성자를 인스턴스화한다고 상상해보십시오. ES5에서는 확장 기호를 사용할 수 있습니다. 이는 다음과 같이 쓸 수 있습니다.
var obj = 새로운 f (... args)
그러나 ES5에서는 확장 문자가 지원되지 않으므로 F.Apply 또는 F.Call에서 다른 매개 변수 만 전달할 수 있습니다. 불행히도, F는 사기이지만 반영을 가진 생성자입니다.
우리는 이것을 ES5로 쓸 수 있습니다 :
var obj = Reflect.construct (f, args)
5 : 액세서 또는 독자를 제어합니다. ES5에서 요소의 속성을 읽거나 속성을 다음과 같이 설정하려면 다음과 같이합니다.
var name = ... // 속성 이름을 stringobj [이름] // 제네릭 속성 LookupObj [name] = value // 제네릭 속성
updateReflect.get and Reflice.Set 메소드는 동일한 작업을 수행 할 수 있으며 RecCiver에 추가 매개 변수를 추가하여 객체의 세터를 설정하고 getter를 위아래로 설정할 수 있습니다.
var name = ... // 속성 이름을 stringReflect.get (obj, name, 래퍼)로 가져옵니다. // obj [name]이 액세서 인 경우``this === wrapper`reflect.set (obj, name, value, 랩퍼)로 실행됩니다. 액세서는 자체 방법을 사용하고 싶지 않지만 이것을 랩퍼 (var var) {vale (value) {vare (value) {var reture (vare). }, bar : function () {alert (1);}}; var wrapper = {bar : function () {console.log ( "Wrapper");}} reflic.set (obj, "foo", "value", 래퍼);6 : __proto__에 직접 액세스하지 마십시오 :
ES5는 Object.getPrototype (OBJ)를 제공하여 Object의 프로토 타입에 액세스하고 ES6도 제공합니다.
recring.getPrototypof (obj) 및 recrom.setPrototypof (OBJ, NewProto), 이것은 객체의 프로토 타입에 액세스하고 설정하는 새로운 방법입니다.
반사
반사는 실제로 function.prototype.apply () ES5의 대체입니다. 반사를 실행하려면 세 가지 매개 변수가 필요합니다.
첫 번째 매개 변수는 다음과 같습니다. 실행되는 함수;
두 번째 매개 변수는 다음과 같습니다. 실행 해야하는 컨텍스트;
세 번째 매개 변수는 다음과 같습니다. 배열 또는 유사 배열은 함수를 실행하기위한 매개 변수로 사용됩니다.
<cript> let fn = function () {this.attr = [0,1,2,3];}; let obj = {}; 반사 (fn, obj, []) console.log (obj); <cript> 반사의 데모. // output : 1; recint.Apply (String.FromCharCode, undefined, [104, 101, 108, 108, 111]); // output : "hello"recrent.Apply (regexp.prototype.exec,/ab/, [ "confabulation"]). index; // 출력 : 4reflect.apply ( "". charat, "ponies", [3]); // output : "i"</script> 반사는 프록시와 함께 사용할 수 있습니다 : {var fn = function () {}; fn.prototype.run = function () {console.log ( "runs out");}; var proxy (fn, {construct (target, arugments) {prox.log "); target (... arugments); // 반사를 사용하는 방법. Apply; 반사. // 출력 먼저 : "프록시 생성자"; 그런 다음 출력 : 실행} recriber.construct () : recint.construct는 실제로 인스턴스화 생성자입니다. 인수 양식을 통해 구현됩니다. 실행 방법이 다릅니다. 효과는 실제로 동일합니다. 생성물의 첫 번째 파라미터는 생성자이고, 두 번째 매개 변수는 매개 변수로 구성된 배열 또는 의사 배열입니다. 기본 사용법은 다음과 같습니다. var fn = function (arg) {this.args = [arg]}; console.log (new fn (1), recil.construct (fn, [1])); // 출력은 동일한 var d = recriber.construct (날짜, [1776, 6, 4]); d 인스턴스의 날짜; // trued.getLyEar (); // 1776 // recriber.construct 및 new Construct So Relect.construct와 새 구성은 동일합니다. 적어도 지금까지는 ... 우리는 세 번째 매개 변수를 반사로 전달할 수 있으며 세 번째 매개 변수는 슈퍼 클래스입니다. 새로운 요소는이 슈퍼 클래스를 상속합니다. <cript> function someconstructor () {} var result = recult.construct (array, [], someconstructor); recint.getPrototypof (result); // someconstructor.protoTypeArray.isArray (결과); // true // orvar fn = function () {this.attr = [1];}; var person = function () {}; person.prototype.run = function () {}; console.log (fn, [], person)); 그래서 우리는 이것을 사용하여 특수 배열을 구현할 수 있습니다. var fn = function () {array.apply (this, arguments); this.shot = () => {console.log ( "heheda");};}; var arr = Reflect.construct (fn, []) Recret.DefineProperty; recriber.defineProperty 부울 값을 반환하고 속성 값은 직접 할당을 통해 객체에 추가됩니다. 추가가 실패하면 전체 객체를 반환하면 오류가 발생합니다. var obj = {}; obj.x = 10; console.log (obj.x) // 출력 : 10; 반사를 사용하여 값을 추가하십시오 .DefineProperty; <cript> var obj = {}; if (recil.defineProperty (obj, "x", {value : 7})) {console.log ( "추가 성공");} else {console.log ( "추가 성공");}; </script> 우리는 방지를 통해 오류를 정의함으로써 오류를 정의함으로써 오류를보고합니다. 반사 .defineProperty 및 false 값이 반환됩니다. var obj = {}; object.preventextensions (obj); object.defineProperty (obj, "x", {value : 101, writable : 거짓, 구성 가능 : 거짓}); // 직접적으로 틀린; console.log (recil.defineProperty (obj, "x", {value : 101})) // return false : 값이 직접 할당되면 값이 올바르게 할당되는지 여부에 관계없이 설정 값이 반환됩니다. <cript> var obj = {}; object.preventextensions (obj); console.log (obj.aa = 1); // 출력 : 1; Console.log (obj.aa) // 출력 : undefined; </script> recince.deleteproperty 사용 : recint.deleteproperty and recint.defineProperty 사용은 유사합니다. DeleteProperty 및 DELETE OBJ.XX의 작동 결과는 동일합니다. 차이점은 사용 양식이 다르다는 것입니다. 하나는 연산자이고 다른 하나는 함수 호출입니다. recriber.deleteproperty (object.freeze ({foo : 1}), "foo"); // falsedElete 객체. freeze ({foo : 1}). foo; // 출력 : false; recond.get () 메소드를 사용하는 데 필요한 두 가지 매개 변수가 있습니다. 첫 번째는 OBJ 대상 객체이고, 두 번째는 속성 이름 객체이고, 세 번째는 선택 사항이며, 이는 독자의 컨텍스트입니다 (this). var obj = {}; obj.foo = 1; console.log (obj.foo); // output : 1; console.log (recil.get (obj, "foo")) // output : 1; recriber.get은 세 번째 매개 변수가 있으면 세 번째 매개 변수는 독자의 컨텍스트로 사용됩니다. var obj = { "foo": 1, get bar () {return this.foo;}}; var foo = {}; foo.foo = "heheda"; console.log (obj, "bar", foo); reflect.getownpropertydescriptor () 메소드를 통해 속성 설명 : recriber.getOwnPropertyDescriptor ({x : "hello"}, "x"); // 객체를 얻을 수 있습니다 : object.getOwnPropertyDescriptor ({x : "1"}, "x"); //이 두 가지의 차이는 객체를 감싸고, 하나는 다음과 같습니다. // 예외 객체를 던지십시오 .GetOwnPropertyDescriptor ( "hello", 0); // output : {value : "h", writable : false, enumerable : true, configurable : false} recil.getPrototype () 메소드 사용 : reclic.getPrototype 및 Object.getPrototypof는 객체의 프로토 타입을 반환합니다. // output : object.protoTyPereFlect.getPrototypof (Object.Prototype); // output : nullReflect.getPrototypof (object.create (null)); // output : nullReflect.AS는 반사를 사용하는 메소드는 연산자와 비슷합니다. 반사. var obj = {x : 0}; Console.log (OBJ의 "X"); var proxy = new proxy (obj, {has : function (target, args) {console.log ( "execute has method"); return recriber.has (target, ... args);}}); Console.log (프록시의 "x"); // 출력 : true; console.log (Reflect.has (프록시, "x")) // 출력 : true; </script>이 데모의 OBJ는 메소드가되는 것과 같으며, 그것은 쓸모가 없으며, 그것은 단지 메소드를 사용합니다 : obj = new proxy ({}, {has (t, k) {return k.startSwith ( "door");}}); 반사. // trueReflect.has (obj, "Dormitory"); // falSeReflect.isextensible () 사용 // 이제이 요소를 확장 할 수 있습니다. val empty = {}; recil.isextensible (빈); // === true //이 개체가 새로운 속성을 확장하지 못하도록 예방 Xtensions 메소드를 사용합니다. 반사 .preventextensions (빈); RELFING.SEXTENSIBLE (빈); // === false //이 객체는 새 속성을 확장 할 수 없으며, 쓰기 속성은 여전히 변경 될 수 있습니다. var sealed = 객체. // === false //이 객체는 완전히 냉동 var var frozen = object.freeze ({}); recil.isextensible (frozen); // === 거짓 반사의 차이점은 recil.Sextensible과 object.isextensible의 차이점이 매개 변수가 올바르지 않으면 하나는 잘못된 것을 던지고 다른 하나는 true 또는 false를 반환한다는 것입니다. recild.isextensible (1); // 잘못된 던지기 : 1은 objectObject.isextensible (1); // return false; // return false; RELCING.OWNYYS () 메소드 사용 : 반사. console.log (reclic.ownkeys ({ "a": 0, "b": 1, "c": 2, "d": 3}); // 출력 : [ "a", "b", "c", "d"] console.log (recil.ownkeys ([])); // [ "길이"] var sym = symbol.for ( "comet"); var sym2 = symbol.for ( "meteor"); var obj = {[sym] : 0, "str": 0, "773": 0, "0": 0, [sym2] : 0, "-1": 0, "8": 0, "Sec // output : /[ "0", "8", "773", "str", "-1", "second str (comet), symbol (meteor)] 반사. 마지막으로, 심볼 유형의 키는 삽입 순서에 따라 정렬됩니다. 객체 속성에 값을 할당 할 때 객체 키의 정렬 규칙은 첫 번째 숫자, 문자열 및 마지막으로 기호 유형의 데이터이기 때문에 정렬은 발생합니다. 반사의 사용법. RELFING.preventExtensions 매개 변수가 객체가 아닌 경우 오류가 발생합니다. val empty = {}; recil.isextensible (빈); // === true // expensextensions를 실행 한 후 객체를 수정할 수 있습니다. 반사 .preventextensions (빈); RELFING.SEXTENSIBLE (빈); // === falSeReFlect.preventExtensions (1); // typeError : 1은 대상이 아닙니다. var obj = {}; recint.set (obj, "prop", "value"); // 출력 : trueconsole.log (obj.prop); // output : "value"var arr = [ "오리", "오리", "오리"]; recint.set (arr, 2, "goose"); // trueconsole.log (arr [2]); // "goose"reflect.set (arr, "length", 1); // trueconsole.log (arr); // [ "duck"]; recint.set (obj)는 recriber.set (obj, undefined, undefined); var obj = {}; recinc.set (obj); // output : true // 위의 코드는 반사와 동일합니다. key (value) {console.log ( "setter"); this.value = value;}, key () {key () {return this.value;}}; recil.set (obj, "key", "heheda", obj); console.log (obj); recel.setPrototypof () recel.setPrototyfo () 방법과 유사합니다. 객체의 프로토 타입을 설정하는데, 이는 객체의 __proto__ 속성을 변경하는 것입니다. // true // 객체 배열로 // [[프로토 타입]]은 null.reflect.setprototypof ({}, null); // 현재 // 현재, obj .__ proto__는 정의되지 않았다. // 객체를 제거하고 재설정 [[프로토 타입]] recriber.setPrototypof (object.freeze ({}), null); // false // 프로토 타입 체인이 루프에 의존하는 경우 false.var target = {}; var proto = object.create (target); recinc.setPrototyp (target, proto); // 거짓