Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
18
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

AngularJSでよく見るDependency Injectionについて

AngularJSでよく見かける書き方

var myModule = angular.module('myModule', []);

とか、

myModule.factory('greeter', function($window) {
return {
  greet: function(text) {
    $window.alert(text);
  }
};
});

というようにAngularJSでは独特の書き方をします。
このような書き方はDependency Injection(DI)という書き方だそうです。

AngularJSでのDIに関するドキュメント
https://docs.angularjs.org/guide/di

AngularJSでのDI部分のコード
https://github.com/angular/angular.js/blob/master/src/auto/injector.js

DIについて

img01.jpg

AngularJSリファレンスという本でもDIについて解説がされています(DIとは、P.129)。

DI(Dependency Injection)とは、あるコンポーネントから別のコンポーネントを利用する際に直接コンポーネントを呼び出すコードを記述するのではなく、設定ファイルやアノテーション機能を使ってコンポーネント間の依存関係を記述し、実行時に依存関係を解決するというデザインパターンです。

DIについて色々と詳しく書かれているので、興味がある人は是非読むのをオススメします。

普通書くときにコンポーネントを直接呼び出すのに慣れています。
1 - 依存関係を記述し、 2 - 実行時に依存関係を記述するという2段感あると一気に複雑に思えます。

簡易版AngularJSでDenpendency Injectionを体験する

AngularJS式Injectionを解説しているブログがありましたので、実際試し、メモしました。

var WelcomeController = function (Greeter) {
  /** I want a different Greeter injected dynamically. **/
    Greeter.greet();
};

AngularJSでは引数の名前がdependencyの名前であります。
引数の名前は重要で、実際のdependencyとdepencyの名前が関連付けられます。

WelocomControlleが動くようにDIを作ってみます。

DIの機能として、1 - 依存関係を記述するメソッドと 2 - 依存関係を実行するメソッドが必要となります。

1 - 依存関係を記述するメソッド

var Injector = {
    depnedencies : {},
    register     : function(name, dependency){
        this.depnedencies[name] = dependency;
    }
}

var RobotGreeter = {
  greet: function() {
    return 'Domo Arigato';
  }
};

Injector.register('Greeter', RobotGreeter);

RobertGreeterというオブジェクトを'greeter'として依存関係を登録する。

2 - 依存関係を実行するメソッド

var Injector = {
    depnedencies : {},
    register     : function(name, dependency){
        this.depnedencies[name] = dependency;
    },
    process : function(target){

    }
}

Injector.register('Greeter', RobotGreeter);
Injector.process(WelcomeController);

WelcomeControllerを実行します。

どのように実行するか、、、という問題が出てきます。

var Injector = {

    dependencies: {},

    process: function(target) {
        var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
        var text = target.toString();
        var args = text.match(FN_ARGS)[1].split(',');

        target.apply(target, this.getDependencies(args));
    },

    getDependencies: function(arr) {
        var self = this;
        return arr.map(function(value) {
            return self.dependencies[value];
        });            
    },

    register: function(name, dependency) {
        this.dependencies[name] = dependency;
    }

};

processでは、正規表現をつかって関数の引数を取ります。
applyで関数に引数を代入します。

サンプルはこんな感じでした。

DIを利用してCanvasを描画する。

// DI

var Injector = {

    dependencies: {},

    process: function(target) {
        var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m;
        var FN_ARG_SPLIT = /,/;
        var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/;
        var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
        var text = target.toString();
        var args = text.match(FN_ARGS)[1].split(',');

        var a = this.getDependencies(args);
        console.log(target);
        console.log("-----\n");
        console.log(a);

        target.apply(this, a);
    },

    getDependencies: function(arr) {
        var self = this;
        return arr.map(function(value) {

            return self.dependencies[value];
        });            
    },

    register: function(name, dependency) {
        this.dependencies[name] = dependency;
    }

};

// ============================
//         Canvasアプリ
// ============================

var CanvasApp = {
  width  : null,
  height : null,
  canvas : null,
  ctx    : null,

  setup  : function(){
    this.width  = window.innerWidth;
    this.height = window.innerHeight;
    this.canvas = document.getElementById('c');
    this.canvas.width = this.width;
    this.canvas.height = this.height;

    this.ctx = this.canvas.getContext('2d');
  },
  draw   : function(){
    this.ctx.fillStyle = '#ff0000';
    this.ctx.fillRect(100, 100, 100, 100);
  }
};

// ============================
//        コントローラ
// ============================

var CanvasAppController = function (paintApp) {
    paintApp.setup();
    paintApp.draw();
};

// 1.dependencyをに'paintApp'としてCanvasAppを登録
Injector.register('paintApp', CanvasApp);

// 2.実行する
Injector.process(CanvasAppController);

結果は下のリンクから見ることができます。
http://codepen.io/kenjiSpecial/pen/GBpnE

DIを知ったつもりになりましたー
AngularJS色々と学ぶことが多いです。。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
18
Help us understand the problem. What are the problem?