惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Hacker News: Ask HN
Hacker News: Ask HN
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Schneier on Security
Schneier on Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
F
Full Disclosure
S
Secure Thoughts
大猫的无限游戏
大猫的无限游戏
www.infosecurity-magazine.com
www.infosecurity-magazine.com
P
Proofpoint News Feed
Hacker News - Newest:
Hacker News - Newest: "LLM"
罗磊的独立博客
S
Schneier on Security
H
Hacker News: Front Page
H
Heimdal Security Blog
美团技术团队
Hugging Face - Blog
Hugging Face - Blog
Apple Machine Learning Research
Apple Machine Learning Research
P
Privacy International News Feed
博客园 - 三生石上(FineUI控件)
P
Palo Alto Networks Blog
PCI Perspectives
PCI Perspectives
NISL@THU
NISL@THU
T
Troy Hunt's Blog
Project Zero
Project Zero
Y
Y Combinator Blog
阮一峰的网络日志
阮一峰的网络日志
G
GRAHAM CLULEY
小众软件
小众软件
月光博客
月光博客
Google DeepMind News
Google DeepMind News
W
WeLiveSecurity
C
Cisco Blogs
腾讯CDC
Blog — PlanetScale
Blog — PlanetScale
I
Intezer
I
InfoQ
WordPress大学
WordPress大学
F
Fortinet All Blogs
T
Threat Research - Cisco Blogs
N
News and Events Feed by Topic
T
Tor Project blog
N
News | PayPal Newsroom
A
Arctic Wolf
有赞技术团队
有赞技术团队
博客园 - Franky
Vercel News
Vercel News
宝玉的分享
宝玉的分享
Application and Cybersecurity Blog
Application and Cybersecurity Blog

Yusuf Aytas

When Code Is Cheap, Does Quality Still Matter? Why Crouching Tiger, Hidden Dragon Is a Masterpiece Why We Ignore Advice The Mirror Is Part of the Machine When Too Many Maps Overlap on One Person The Work Runs on Different Maps Your Work Introduces You Trial By Fire The Dude Why Headcount Math Lies Capacity Is the Roadmap The Roadmap Is Not the System Torres del Paine W Trek Escaping Status Theater Incentives Drive Everything Scaling Culture Without Dilution What Good Looks Like Why Airport Security Feels Random Why Politics Appear How to Work with Me The Janus Protocol Multi-Horizon Delivery Framework What Good Execution Looks Like Managing Your Manager Why Kingdom of Heaven’s Director’s Cut Is Better AI Broke Interviews Most of What We Call Progress Managers Have Been Vibe Coding All Along Stop Wasting Brainpower Why Over-Engineering Happens Prisoner's Dilemma Climbing No More The Weekly Win Mevlana Candy Brewing Turkish Tea Onboarding Your Engineering Manager Technical Deep Dives Yapay Zekâ Çağında Bilgisayar Mühendisliği Building Remote Teams From Idea to Launch in 2 Weeks Reflecting on Software Engineering Handbook Representing the Business New Manager Survival Guide Take Self Reviews Seriously Chasing Real Respect The Invisible Difference Learning the Johari Window Management is a Lonely Place Simple Task Management AI Balance in Work PIP Manager Insights Engineering Manager Interview Preparation Work-Life Balance as a Manager Bridging the Management Disconnect Tech Hiring Bubble Bursts Traits for EMs Simple Acts of Recognition Matter The Question I Ask Every New Report The Reality of an Employer's Market Bridging Ideals and Reality Hiring Red Flags Why The Godfather Is So Damn Good Subteam Tenets No Fluff Please Losing a Top Performer Balancing Act of Reliability Building Trust in Engineering Teams Ideal Number of Direct Reports Overriding a People Leader’s Decision From Misperception to Promotion Perception vs Perspective Setting Goals From Engineer to Manager Getting Delegation Right Interviewing Your Future Boss Celebrating Our Book in Iceland Operational Skills Needed On Writing Software Engineering Handbook Charlie Munger Quotes Working with Dependencies From Las Vegas to Canyons Navigating Layoffs Handling Competitive Dynamics A Weekend Getaway to Malta Engineering Health Essentials Should Dev Managers Code? Confronting the Life on Pause Winning Eleven Kindness is A Choice Bireysel Katılımcılar ve Yöneticiler Leading from Where You Are The Subtle Art of Listening Coding in Leadership The Power of Consistency The Making of a Leader The Path to Leadership Embracing TikTok Talent Sourcing Journey Leading Self Managing Teams Cracking Coding Bottlenecks
Dependency Injection in JavaScript
Yusuf Aytas · 2013-05-22 · via Yusuf Aytas

Published · 4 min read

Dependency injection is about removing the hard coded dependencies and providing way of changing dependencies in compile-time or run-time. This pattern has been exercised in several frameworks like Spring(Java). It is also becoming popular in JavaScript community. There are libraries that support dependency injection like Angular.js, Require.js, Inject.js and more. Following recent developments, we will present what is dependency injection, its advantages and simple implementation of this pattern in JavaScript. Dependency injection is to ask for instance of the classes you need and somebody(injector or factory) provides those instances to you in either compile-time or run-time. There are 3 types of dependency injection : setter, constructor and interface injection. For any of those injection types, one needs a container or injector which can provide dependencies we need. Containers or injectors provides those dependencies by using configuration, types and qualifiers. Now, let's have a look at the uml diagram below. In this diagram ItemController uses a logger to log its events and it may use one of those Logger implementations. Having configured which one to use, Injector injects instance of Logger to the ItemController.

Dependency injection class diagramDependency injection class diagram

Having presented dependency injection, let's observe why we need this. There can be two main reason to favor dependency injection : first is to improve maintainability of the code, second is to make it easy to test the code. Besides, writing code through an interface is always preferable in terms of abstraction and reusability. By having interfaces instead of implementation, one can change the implementation and remain the rest untouched. This provides you to replace actual implementation with the mock implementation for testing purposes. Furthermore, you can replace implementation of your interface whenever you want by just configuration. Now, let's see how we implement dependency injection in JavaScript.

var Injector = {
   dependencies: {},
   add : function(qualifier, obj){
      this.dependencies\[qualifier\] = obj; 
   },
   get : function(func){
      var obj = new func;
      var dependencies = this.resolveDependencies(func);
      func.apply(obj, dependencies);
      return obj;
   },
   resolveDependencies : function(func) {
      var args = this.getArguments(func);
      var dependencies = \[\];
      for ( var i = 0; i < args.length; i++) {
         dependencies.push(this.dependencies\[args\[i\]\]);
      }
      return dependencies;
   },
   getArguments : function(func) {
      //This regex is from require.js
      var FN\_ARGS = /^function\\s\*\[^\\(\]\*\\(\\s\*(\[^\\)\]\*)\\)/m;
      var args = func.toString().match(FN\_ARGS)\[1\].split(',');
      return args;
   }
};

The first thing we need a configuration to provide necessary dependencies with qualifiers. To do that, we define a dependency set as dependencies in the Injector class. We use dependency set as our container which will take care of our object instances mapped to qualifiers. In order to add new instance with a qualifier to dependency set, we define an add method. Following that, we define get method to retrieve our instance. In this method, we first find the arguments array and then map those arguments to dependencies. After that, we just construct the object with our dependencies and return it. To figure out, how we use above implementation, we give an example as follows.

var Logger = {
   log : function(log) {}
};
var SimpleLogger = function() {};
var FancyLogger = function(){};

SimpleLogger.prototype = Object.create(Logger);
FancyLogger.prototype = Object.create(Logger);

SimpleLogger.prototype.log = function(log){
   console.log(log);
}

FancyLogger.prototype.log = function(log){
   var now = new Date();
   console.log(now.toString("dd/MM/yyyy HH:mm:ss fff") + " : "+ log);
}

var ItemController = function(logger){
   this.logger = logger;
};
ItemController.prototype.add = function(item) {
   this.logger.log("Item\["+item.id+"\] is added!");
};
Injector.add("logger", new FancyLogger());
var itemController = Injector.get(ItemController);
itemController.add({id : 5});

Above, we have defined an interface(you can quickly look at how to define interfaces from here) as Logger and implemented Logger with FancyLogger and SimpleLogger. We added instance of FancyLogger to the Injector. After that, we tried to get instance of ItemController via get method of Injector. In this post, we have tried to give some insight about dependency injection; however, there is a lot left to talk like dependency graph. As this is an introduction for dependency injection concept, we did not go into much detail. You can read source code of angular.js or require.js to find out how there are doing the staff. Consequently, we have tried to explain what is dependency injection and advantages of it as well as implementation of a simple inversion of control container.