AngularJS中的依賴(lài)注入實(shí)際應(yīng)用場(chǎng)景有哪些?
網(wǎng)友解答: 所謂依賴(lài)注入,通俗地舉例,有個(gè)人養(yǎng)了一只寵物,他可以喂寵物吃東西,寵物會(huì)自己吃:function PetKeeper(pet) {this.pet = pet;}PetKee
所謂依賴(lài)注入,通俗地舉例,有個(gè)人養(yǎng)了一只寵物,他可以喂寵物吃東西,寵物會(huì)自己吃:
function PetKeeper(pet) {
this.pet = pet;
}
PetKeeper.prototype.feed = function(food) {
this.pet.eat(food);
};
function Pet(type) {
this.type = type;
}
Pet.prototype.eat = function(food) {
alert("I am a " + this.type + ", I'm eating " + food);
};
var tom = new Pet("cat");
var jerry = new Pet("mouse");
var keeper = new PetKeeper(tom);
keeper.feed("fish");
keeper.pet = jerry;
keeper.feed("rice");
這個(gè)例子里,pet是外部注入的,在feed函數(shù)定義里,并不知道pet到底是什么(在帶接口的語(yǔ)言里,至少還是知道是個(gè)什么,在動(dòng)態(tài)語(yǔ)言里就是兩眼一抹黑了……),只有當(dāng)它被調(diào)用的時(shí)候,才知道pet是什么。
這個(gè)過(guò)程的好處是什么呢?如果我們?cè)赑etKeeper內(nèi)部去創(chuàng)建tom或jerry,就表示PetKeeper要對(duì)Pet產(chǎn)生依賴(lài)。一個(gè)對(duì)別人有依賴(lài)的東西,它想要單獨(dú)測(cè)試,就需要在依賴(lài)項(xiàng)齊備的情況下進(jìn)行。如果我們?cè)谶\(yùn)行時(shí)注入,就可以減少這種依賴(lài),比如在單元測(cè)試的時(shí)候使用模擬類(lèi)就行。
比如你有一個(gè)a,依賴(lài)于b,實(shí)際業(yè)務(wù)中,b的實(shí)現(xiàn)很復(fù)雜:
function A(b) {
this.b = b;
}
A.prototype.a1 = function() {
alert(100 + this.b.b1());
};
function B() {}
B.prototype.b1 = function() {
//這里可能很復(fù)雜而且不好模擬,比如依賴(lài)于生產(chǎn)環(huán)境的一些調(diào)用
}
那么,我如何用單元測(cè)試來(lái)驗(yàn)證A自身的邏輯是正確的呢?如果有強(qiáng)依賴(lài),這里就不好辦了,必須實(shí)例化真正的B,但是B的調(diào)用要依賴(lài)于生產(chǎn)環(huán)境。換個(gè)方式考慮,我們用一個(gè)接口與B相同的類(lèi)來(lái)做模擬,只要改變它的返回值,實(shí)現(xiàn)各種邊界條件,把它的實(shí)例注入到A的構(gòu)造函數(shù)中,就可以讓A自身的邏輯得到測(cè)試了。
function MockB() {}
MockB.prototype.b1 = function() {
return 99;
};
在AngularJS里,依賴(lài)注入的目的是為了減少組件間的耦合,它的實(shí)現(xiàn)是這個(gè)過(guò)程:
function Art(Bar, Car) {}
我怎么知道這個(gè)Art在實(shí)例化的時(shí)候要傳入Bar和Car的實(shí)例呢?形參名稱(chēng)是沒(méi)法取到的,所以只有狠一點(diǎn),用toString()來(lái)取到剛才這一行字符串,然后用正則表達(dá)式取到Bar和Car這兩個(gè)字符串,然后到模塊映射中取到對(duì)應(yīng)的模塊,實(shí)例化之后傳入。
但是這樣也有問(wèn)題,如果這個(gè)js被壓縮了,很可能命名都變了,壓縮成了這樣:
function a1(b1, b2) {}
這時(shí)候再這樣就不知道原先是什么類(lèi)型了。在這里,有類(lèi)型聲明的語(yǔ)言就不會(huì)有問(wèn)題,比如:
function art(bar:Bar, car:Car) : Art {}
就算你把a(bǔ)rt, bar, car都改名了,也還是能知道類(lèi)型,但js里不行。所以,怎么辦呢?
aaa.controller("Art", [function(Bar, Car) {}, "Bar", "Car"]);
注意在AngularJS里面,他很可能建議你這么寫(xiě),但也可以這么寫(xiě):
Art.$inject = ["Bar", "Car"];
這么一來(lái),我只要拿到Art,就能取到依賴(lài)項(xiàng)的名稱(chēng)了,就可以實(shí)例化再注入,也不怕壓縮了。