本文将会对依赖注入做一个简单的介绍。
假如我们要从零开始做一个 to-B
方向的平台,最开始的想法是什么呢?
- 在前端蛮荒纪,什么都是从零开始,直接撸 html、js、css,所以现在是这样子的。
- 渐渐的前端涌入了很多人,大家开发出很多好用的模块,再后来,Grunt、Browserify、gulp、webpack 等前端打包工具,npm、yarn 等包管理工具横空出世,我们渐渐地可以使用其他人开发出的模块去开发我们的网站,这就是广义的依赖注入。
- 再到后来,前端涌入了更多的人,
Angular、React、Vue
横空出世,我们开始采用框架来开发网站,但是我们不需要关心React
里面用了什么模块、进行了什么处理,这就是广义上的控制反转。
总的来说,前端的发展史就是一个面向对象语言的进化史呢。
众所周知,javascript 是一门面向对象(Object-oriented programming,OOP)的语言,依赖注入(DI)和控制反转(IoC)是具体的手段,是OOP理论中依赖倒置原则的体现形式,通过信息隐藏来降低对象之间的耦合。
将创建对象的任务转移给其他 class,并直接使用依赖项的过程,被称为“依赖项注入”。(DI)
IOC 就是一个可以自动实例化具体类并且管理各对象之间关系的容器,有了这个自动化的容器,我们关注的就不是具体的关系,而是上升到只需关注抽象之间的关系,而且还可以省去手动实例化。
事实上我们使用某些npm
的过程就是一种对依赖注入的使用了。再比如以下 jquery
的注入。
!(function ($, window) {
...
})(jQuery, window)
没有使用依赖注入示例模块
// team.js
var User = require('./user');
function getTeam(teamId) {
return User.find({teamId: teamId});
}
module.exports.getTeam = getTeam;
使用依赖注入示例模块
// team.js
function Team(options) {
this.options = options;
}
Team.prototype.getTeam = function(teamId) {
return this.options.User.find({teamId: teamId})
}
function create(options) {
return new Team(options);
}
或者尝试 es6 的写法
// team.js
class Team {
constuctor(options) {
this.options = options;
}
getTeam: (teamId) => {
return this.options.User.find({teamId: teamId})
}
}
function create(options) {
return new Team(options);
}
比较显示使用依赖注入的模块有:
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}
(该代码截取自 nest 官网)
或者是这样的代码:
import { Component } from '@angular/core';
@Component({
selector: 'hello-world',
template: `
<h2>Hello World</h2>
<p>This is my first component!</p>
`,
})
export class HelloWorldComponent {
// The code in this class drives the component's behavior.
}
(该代码截取自 Angular 官网)
学习了依赖注入后,我们可以更专注于模块的封装,从而更好的实现高内聚低耦合的代码。