理解 JavaScript 中的依赖注入
依赖注入对于初学者来说是一个相当复杂的主题。了解这个概念可能并非必要,但了解它会帮助你更好地设计代码。
让我们从定义开始。
依赖注入 - 依赖注入是一种对象接收其所依赖的其他对象的技术(来源:维基百科)。
现在让我们尝试稍微分解一下这个定义。先从对象开始。对象是类的一个实例。例如
// lets define a class dog
class Dog{
speak(){
console.log("wuff");
}
}
//now lets create object dog
const fluffy = new Dog();
在上面的例子中,我们有一个 Dog 类,而 Fluffy 是 Dog 类的对象。当我们新建一个类时,我们会创建该类的一个对象。这是在 JavaScript 中创建对象的方法之一(也是在 C# 和 Java 等语言中创建对象的常用方法)。
现在让我们看一个两个对象相互依赖的例子。
class Pet{
whatDoesMyPetSay(){
const pet = new Dog();
pet.speak();
}
}
const fluffy = new Pet();
fluffy.whatDoesMyPetSay();
// response will be "wuff"
如我们所见,Pet 类依赖于 Dog 类。因此,为了达到我们想要的效果,我们需要在 Pet 类中创建一个 Dog 类的实例。现在,这个类不可重用,因为它与 Dog 类绑定在一起。如果有人把猫作为 Pet,他们将无法使用这个类。这就是所谓的紧耦合代码。
现在,让我们修改这段代码,并尝试使用依赖注入来满足所有其他宠物主人的需求。但首先,让我们创建一个猫类。
class Cat{
speak(){
console.log("meow");
}
}
cat 类也必须实现相同的方法才能使依赖注入正常工作。在 C# 和 Java 等语言中,这是通过使用接口来实现的。但 JavaScript 中没有这样的方法,所以开发者需要自己记住它。现在让我们看看 pet 类的新实现。
class Pet{
//usually we have a private variable that needs
//to be accessed only in this class
#pet;
//create a constructor that recieves the dependent
//object
constructor(pet){
this.#pet = pet;
}
whatDoesMyPetSay(){
//as long as pet class implements speak method we are fine
this.#pet.speak();
}
}
//what does fluffy the dog say?
const fluffy = new Pet(new Dog());
fluffy.whatDoesMyPetSay();
//The response will be "wuff"
//what does milo the cat say?
const milo = new Pet(new Cat());
milo.whatDoesMyPetSay();
//The response will be "meow"
现在,我们已经从 pet 类内部移除了依赖项,并将其交给了该类的调用者。这提升了 pet 类的可重用性。这是一个非常简单的示例,目的只是为了理解依赖注入,而不是实现它。在现实世界中,依赖项甚至会从调用者那里抽象出来,并交给一个新对象,这个新对象通常称为注入器 (Injector)。
为什么不在 JavaScript 中使用依赖注入
如果你读到这里,我希望你对依赖注入的概念更加清晰了。现在让我们看看一些我们可能不想使用依赖注入的原因。
- 与 C# 和 Java 等纯粹基于类的语言不同,JavaScript 在功能分组方面提供了极大的灵活性。很多时候,你甚至不需要使用类,只需使用函数就足够了。在这种情况下,尝试实现依赖注入只会增加不必要的复杂性。
- JavaScript 本质上也是动态的。你可以覆盖并使用 JavaScript 中的任何函数实现。因此,我们应该利用这些特性,而不是依赖注入来对代码进行单元测试。
归根结底,作为一名开发人员,我们应该意识到,没有一种解决方案可以解决所有问题。我希望通过本文,您能够更好地选择解决方案。
文章来源:https://dev.to/_mohanmurali/understanding-dependency-injection-in-javascript-3374