요즘에는 모든 프레임워크가 모듈화되고 있으며, 프론트엔드 자바스크립트도 예외는 아닙니다. 각 모듈은 특정 기능을 담당하며 모듈 간에 상호 의존성이 있습니다. 따라서 JavaScript에서 종속성 주입을 어떻게 구현합니까? (Javascript 종속성 주입, 모든 주요 프레임워크에는 해당 구현이 있습니다. 여기서는 구현 아이디어만 배웁니다.)
다음 요구 사항:
이미 정의된 서비스 모듈 키-값 컬렉션이 있다고 가정합니다. func 새로 추가된 서비스의 경우 매개변수 목록은 서비스 종속성입니다.
var services = { abc : 123, def : 456, ghi : 789 } // 일부 서비스가 정의되었다고 가정
function Service(abc, ghi){ this.write = function(){ console.log(abc); console.log(ghi); } } function Activitor(func){ var obj; // 实现 return obj; }
해결책:
어떤 메커니즘(반사?)을 사용하여 func에 의해 정의된 매개변수 목록을 꺼내고 값을 하나씩 할당합니다. 그런 다음 일부 메커니즘(Activitor?)을 통해 기능을 인스턴스화합니다.
해결책:
1. func의 매개변수 목록을 가져옵니다.
매개변수 목록을 가져오는 방법은 무엇인가요? 가장 먼저 떠오르는 것은 반사 메커니즘입니다. 그럼 자바스크립트에는 리플렉션이 있나요? 현재는 eval(str) 함수 사용법만 알고 있는데, 매개변수 목록을 얻기 위한 관련 구현은 없는 것 같습니다. func.arguments 정의를 다시 살펴보면 이 속성은 func가 호출되고 매개변수가 전달될 때만 유효하며 요구 사항을 충족할 수 없습니다.
func.toString() 이후 문자열을 처리하여 매개변수 목록을 얻을 수 있나요?
한번 해보자:
function getFuncParams(func) { var matches = func.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m); if (matches && matches.length > 1) return matches[1].replace(/\s*/, '').split(','); return []; };
이제 func 매개변수 목록 배열을 얻게 됩니다.
2. 매개변수 목록을 기반으로 종속성 찾기:
매개변수 목록, 즉 종속성 목록을 얻은 후 종속성을 매개변수로 전달하는 것은 매우 간단합니다. .
var params = getFuncParams(func); for (var i in params) { params[i] = services[params[i]]; }
3. 종속성 매개변수 전달 및 인스턴스화:
javascript에 func.constructor가 있다는 것을 알고(thisArg,[arg[,arg , [arg,[…]]]]) 및 apply(thisArg,args…) 두 함수 모두 인스턴스화 func 작업을 구현할 수 있습니다. 호출 함수의 첫 번째 매개변수는 이 포인터이고, 나머지는 매개변수 목록입니다. 이는 func 매개변수 목록을 알고 있는 경우 사용하기에 적합하지만 내 요구 사항을 충족하지 않습니다. 두 번째 적용 함수를 보면 첫 번째 매개변수도 이 포인터이고, 두 번째 매개변수도 매개변수 배열이다. 호출되면 자동으로 func의 매개변수 목록에 값을 하나씩 할당하는데, 이는 바로 내 조건을 충족한다. 필요합니다.
코드는 대략 다음과 같습니다.
function Activitor(func){ var obj = {}; func.apply(obj, params); return obj; }
이 시점에서 func의 인스턴스를 생성하고 func에 필요한 매개변수를 전달할 수 있습니다.
4. 인쇄 및 테스트:
전체 코드:
var // 假设已定义好某些Service services = { abc: 123, def: 456, ghi: 789 }, // 获取func的参数列表(依赖列表) getFuncParams = function (func) { var matches = func.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m); if (matches && matches.length > 1) return matches[1].replace(/\s+/, '').split(','); return []; }, // 根据参数列表(依赖列表)填充参数(依赖项) setFuncParams = function (params) { for (var i in params) { params[i] = services[params[i]]; } return params; }; // 激活器 function Activitor(func) { var obj = {}; func.apply(obj, setFuncParams(getFuncParams(func))); return obj; } // 定义新Service function Service(abc, ghi) { this.write = function () { console.log(abc); console.log(ghi); } } // 实例化Service并调用方法 var service = Activitor(Service); service.write();
콘솔이 성공적으로 인쇄되었습니다!