谈到依赖注入,必须先理解 IOC 与 DI。
IOC 控制反转的设计模式可以大幅度地降低了程序的耦合性。而 装饰器在 VSCode 的控制反转设计模式里,其主要作用是实现 DI 依赖注入的功能和精简部分重复的写法。由于该步骤实现较为复杂,我们先从简单的例子为切入点去了解装饰器的基本原理。
@serviceA 和 @serviceB 是参数装饰器,用于处理参数,是由 createDecorator 方法创建的。
@参数装饰器使用方法:接收三个参数
class C {
constructor(@serviceA private a: A, @serviceB private b: B) {}
}
所有参数装饰器均由 createDecorator 方法创建,'A' 和 'B',均是该装饰器的唯一标识。
const serviceA = createDecorator("A");
const serviceB = createDecorator("B");
装饰器首先判断是否被缓存,如果有被缓存则取出已经缓存好的参数装饰器,如果没被缓存,则创建一个 serviceIdentifier 的参数装饰器。
function createDecorator<T>(serviceId: string): ServiceIdentifier<T> {
if (_util.serviceIds.has(serviceId)) {
return _util.serviceIds.get(serviceId) as ServiceIdentifier<T>;
}
}
serviceIdentifier 参数装饰器只做了一件事就是触发 storeServiceDependency 把所有依赖项给存起来,存装饰器本身 id,参数的下标 index 以及是否可选 optional。
const id = function serviceIdentifier(target: Ctor<T>, key: string, index: number): void {
storeServiceDependency(id, target, index, false);
};
id.toString = () => serviceId;
_util.serviceIds.set(serviceId, id);
storeServiceDependency 本质是往 target 即 class C 上设置两个静态属性 $di$target 和 $di$dependencies 上面分别存 target,自身还要再存一次自身 target 是为了判断是否已经存过依赖。
C.$di$target; // class C
C.$di$dependencies[0].id.toString(); // A 或者 B
C.$di$dependencies; // [{id: serviceIdentifier, index: 1, optional: false}, {id: serviceIdentifier, index: 0, optional: false}]
除了存在类上,还存在了 _util.serviceIds 上。
当类声明的时候,装饰器就会被应用,所以在有类被实例化之前依赖关系就已经确定好了。把 ts 编译就可以证明这点,可以看到 __decorate 在类声明的时候,装饰器就会被执行了,
var C = /** @class */ (function() {
function C(a, b) {
this.a = a;
this.b = b;
}
C = __decorate([__param(0, serviceA), __param(1, serviceB)], C);
return C;
})();
紧接着就到了 ServiceCollection,这里会将装饰器作为 key 唯一标识,实例化的类作为 value,全部存到 svrsCollection 中,svrsCollection 的实现也很简单,直接用 Map 方法存起来。
const aInstance = new A();
const bInstance = new B();
const svrsCollection = new ServiceCollection();
svrsCollection.set(serviceA, aInstance);
svrsCollection.set(serviceB, bInstance);
后续只需要使用 get 方法并传入对应的参数装饰器就可以获取对应的实例化好的类了。
svrsCollection.get(serviceA); // new A()
svrsCollection.get(serviceB); // new B()
InstantiationService 是实现依赖注入的核心,它是以参数装饰器,例如 serviceA 和 serviceB 等 ServiceIdentifier 为 key 在私有变量 services 中保存所有依赖注入的被实例化好的类。services 保存的是 svrsCollection。
const instantiationService = new InstantiationService(svrsCollection);
它暴露了三个公开方法:
createInstance 方法是实例化的核心方法:
const cInstance = instantiationService.createInstance(C, "L", "R") as C;
首先是获取 ctorOrDescriptor 也就是类 class C 和需要传入非依赖注入的参数 rest。
const result = this.createCtorInstance(ctorOrDescriptor, rest);
然后使用 getServiceDependencies 把挂载 class C 静态属性的 $di$dependencies 给获取出来并排序,因为存的时候顺序是倒序的
const serviceDependencies = _util
.getServiceDependencies(ctor)
.sort((a, b) => a.index - b.index);
取出来的依赖项 serviceDependencies 主要是为了遍历并获取里面的参数装饰器 serviceA 和 serviceB。
const serviceArgs: any[] = [];
for (const dependency of serviceDependencies) {
const serviceInstance = this.getOrCreateServiceInstance(dependency.id);
serviceArgs.push(serviceInstance);
}
getOrCreateServiceInstance 本质就是从 services 即 svrsCollection 中获取实例化好的类。
const instanceOrDesc = this.services.get(id);
// 相当于 id 即参数装饰器
// svrsCollection.get(id);
当把所有的这些实例化好的类取出来放到 serviceArgs 中后,由于参数装饰器是类实例化的时候就执行完并收集好依赖项,所以 serviceArgs 就是对应 ctor 即 class C 需要注入的依赖参数,合并非依赖参数就能帮助我们成功实例化好我们的 ctor 类。
new ctor(...[...serviceArgs, ...args]);
原文来自:https://github.com/Wscats/dependency-injection/blob/master/README.CN.md
很多童鞋可能年后有自己的一些计划,比如换份工作环境,比如对职业目标有了新的打算。当然面试这一关不得不过,大概又不可能系统性的复习,这里罗列一些 重点 面试的知识点和文章,
什么是webpack和grunt和gulp有什么不同?什么是bundle,什么是chunk,什么是module?什么是Loader?什么是Plugin?如何可以自动生成webpack配置?webpack-dev-server和http服务器如nginx有什么区别?
多问问应聘者高层次的知识点,如果能讲清楚这些概念,就说明即使应聘者没怎么接触过 JavaScript,也能够在短短几个星期之内就把语言细节和语法之类的东西弄清楚。
面试比棘手的技术问题要多,这篇文章整理了37个JavaScript基本面试问题和解答,这些仅仅是作为指导。希望对前端开发的你有所帮助!
React常见面试题:React中调用setState之后发生了什么事情?React中Element与Component的区别?优先选择使用ClassComponent而不是FunctionalComponent?React中的refs属性的作用是什么?React中keys的作用是什么?
题目大意为:JS 环境下,如何让 a == 1 && a == 2 && a == 3 这个表达式返回 true ?这道题目乍看之下似乎不太可能,因为在正常情况下,一个变量的值如果没有手动修改,在一个表达式中是不会变化的。
10道JavaScript题目:累加函数addNum、实现一个Person类、实现一个arrMerge 函数、实现一个toCamelStyle函数、setTimeout实现重复调用、实现一个bind函数、实现一个Utils模块、输出一个对象自身的属性
面试开场白总缺少不了自我介绍,一方面是面试官想听听你对自己的介绍,顺便有时间看看简历上的描述,是否与口述一致。另一方面就是看看你简历上做过什么项目,用到了哪些技术栈,一会儿好提问你。
把面试当做学习,这个过程你会收益很大。前端知识很杂,可能实际工作中用到的技术,像框架都是跟着公司的要求走的,像我最近也在看React啦,Vue和React都对比着再学习
vue上手可以说是比较轻松而且简单,如果你用过angular,react,你也会很喜欢vue。vue的核心思想依旧是:构建用户界面的渐进式框架,关注视图的变化。这也是为什么新建的文件是结构是template script style
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!