AngularJs 의존 주입 연구
의존 주입이란 무엇일까, 내 이해, 간단하게 말하자면 내 물건은 내가 가지고 있지 않다는 것이다. 나는 내가 의존하는 그 사람이 나를 도와 들고 싶다. 내가 필요할 때 그가 나에게 주면 된다.물론 이것은 간단한 이해일 뿐, 코드로 해석하는 것이 비교적 명확하다.
여기에는 기능이 하나 있는데, 매우 간단하다.
var a = function(name){console.log(name);}
우리는 그것을 호출한다.
a('abc');//abc
그러면 제가 위에서 말한 바와 같이 제가 파라미터를 전달하지 않을 수 있을까요? 예를 들면:
a();//undefined
어떻게 해야만 다른 사람이 우리를 도와 이 매개 변수를 주입할 수 있습니까?
var inject = function(name,callback){
return function(){
callback(name);
}}
이렇게 매개 변수를 정의할 때 다음과 같이 전달합니다.
a = inject('abc',a)
우리는 다시 a 방법을 사용한다.
a();//abc
이것은 사실 가장 간단한 의존 주입이다. 물론 이렇게 간단하면 안 된다. 사실 이것은 매우 무의미한 것이다. 다음은 깊은 angularjs를 살펴보자.
var MyController = function($scope){
$scope.test = 1;}
위의 코드는angularjs의 controller에 scope를 사용했습니다. 이렇게 하면 문제가 보이지 않습니다. 아래를 보십시오.
var MyController = function($scope,$http){
$scope.test = 1;
$http.get('');}
위의 이 코드는 원래의 기초 위에서 http를 추가했다. 그러면 문제가 생겼다. angular는 controller를 호출할 때 내가 scope가 필요한지 http가 필요한지 두 개가 필요한지 어떻게 알겠는가. 이것은angular의 의존 주입에 달려 있다. 그러면 우리가 시뮬레이션을 해 보자.
만약angular가 없는 상황에서 우리는:
var MyController = function($scope,$http){
$scope.test = 1;
$http.get('');}MyController();//undefined
틀림없이 틀릴 거야. 그리고 우리 inject를 수정하자.
var inject = {
dependencies: {},
register: function(key, value) {
this.dependencies[key] = value;
},
resolve: function(deps, func, scope) {
var arr = [];
for (var i = 0 ; i < deps.length ; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
console.log(arr);
return function(){
func.apply(scope || {}, arr);
}
}
}
여기에서 설명하자면, 우리는 dependencies로 모든 의존을 저장하고,register로 등록 의존을 실현하고,resolve 방법으로 주입을 실현했다.
그리고 우리는 angular를 모방하여 몇 개의 모듈을 미리 등록합니다.
inject.register('$http', {'get':function(){console.log('get')}});inject.register('$scope', {'test':''});inject.register('$location', {'hash':function(){console.log('hash')}});
그리고 우리는 주입할 수 있다.
MyController = inject.resolve(['$http','$scope'],MyController);MyController();
우리는 http와scope만 필요합니다. 그래서 우리는 두 개만 전달했습니다. 이렇게 하면 의존 주입을 해결하는 것 같지만 많은 문제가 있습니다. 예를 들어 제가 두 개의 매개 변수의 위치를 교환하면 안 됩니다.
그래서 angularjs의 원본을 뒤져서 찾았습니다.
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
.....
function annotate(fn) {
.....
fnText = fn.toString().replace(STRIP_COMMENTS, '');
argDecl = fnText.match(FN_ARGS);
.....
}
우리는 세부 코드를 무시하고 우리가 필요로 하는 것만 보았다.annotate 방법은 우리의resolve 방법과 매우 비슷하다.이것은 전달된func를 문자열로 변환하여 주석 코드를 삭제하고 그 중의 매개 변수를 추출합니다.실행 결과를 보고 Resolve 방법을 수정합니다.
resolve: function(deps, func, scope) {
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var fnText = func.toString().replace(STRIP_COMMENTS, '');
var argDecl = fnText.match(FN_ARGS);
console.log(argDecl);
}
argDecl 인쇄:
["function ($scope,$http)", "$scope,$http", index: 0, input: "function ($scope,$http){↵ $scope.test = 1;↵ $http.get('');↵ }"]
보시다시피 이 수조는func의 매개 변수를 받았습니다.argDecl[1]="$scope, $http";
이것에 근거하여 우리는 Resolve를 수정한다.
resolve: function(func, scope) {
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var fnText = func.toString().replace(STRIP_COMMENTS, '');
var argDecl = fnText.match(FN_ARGS);
console.log(argDecl);
var deps = argDecl[1].split(',');
var arr = [];
for (var i = 0 ; i < deps.length ; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
return function(){
func.apply(scope || {}, arr);
}
}
OK, 이번에 우리는 매개 변수의 순서를 신경 쓸 필요가 없다. 그러나angular는 우리가 생각하는 것보다 훨씬 많다. 대부분의 경우 우리의 js는 압축되어야 하기 때문에function의 실삼은 교체될 것이다. 만약 그렇다면, 우리의 이 방법의argDecl[1]="$scope, $http";argDecl[1]="r,t";이와 같은 변수는 어떻게 해결해야 합니까?
angular 공식적으로는 다음과 같은 해석이 있다.
압축으로 인한 문제를 극복하기 위해 컨트롤러 함수에 $inject 속성에 서비스 식별자에 의존하는 그룹을 부여하면 다음과 같다.
var MyController = ['$scope', '$http', function($scope, $http) { }];
그렇다면 우리 이 방법에 쓰이면 어떻게 실현해야 하는가?그럼 우리 angular의 원본을 봅시다.
....} else if (isArray(fn)) {
last = fn.length - 1;
assertArgFn(fn[last], 'fn')
$inject = fn.slice(0, last);
} else {....
보셨죠? 수조에 사용된 이유도 있습니다. 필요한 의존을 방법 앞에 써서 우리의 reslove 방법에 적용합니다.
resolve: function(func, scope) {
if (isArray(func)) {
var last = func.length - 1;
var deps = func.slice(0, last);
func = func[last]
} else {
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var fnText = func.toString().replace(STRIP_COMMENTS, '');
var argDecl = fnText.match(FN_ARGS);
var deps = argDecl[1].split(',');
}
var arr = [];
for (var i = 0 ; i < deps.length ; i++) {
if (this.dependencies.hasOwnProperty(deps[i])) {
arr.push(this.dependencies[deps[i]])
}
}
return function(){
func.apply(scope || {}, arr);
}
}
OK, 여기까지만 하면 우리 inject로 angular의 의존 주입을 모의할 수 있습니다. 물론 진정한 angular의 의존 주입에는 아직 많은 것들이 있습니다. 여기는 상세하게 설명하지 않았습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.