Angularのファクトリとサービスの違い

- [Angularのファクトリとサービスの違い](#sec-1)
- [javascirptの new 演算子の有無に着目したオブジェクト生成](#sec-2)

# Angularのファクトリとサービスの違い<a id="orgheadline1"></a>

Angular1系のファクトリーとサービスの違いを説明します。 所属プロジェクトにおいて以下のコードのようなものが見受けられました。主にプロジェクトメンバー向けの記事ですが、それ以外の人でも役立つかもしれません。

最初にお断りしておきます。本記事で書いたコードは動作検証しておりません。

```javascript
angular
  .module('hoge')
  .factory('hogeFactory', function(){
    function func1 (){}
    function func2 (){}
    function func3 (){}
    return {
      func1: function(){
        return func1();
      },
      func2: function(){
        return func2();
      },
      func3: function(){
        return func3();
      },
    };
  });
```

これでは関数コールが1回無駄になります。

    function functionName (){}

と書くことは、

    var functionName = function(){}

と同じです。

したがいまして、以下のコードのように修正できます。

```javascript
angular
  .module('hoge')
  .factory('hogeFactory', function(){
    function func1 (){}
    function func2 (){}
    function func3 (){}
    return {
      func1: func1,
      func2: func2,
      func3: func3,
    };
  });
```

サービスを使うと以下のように書きます。

```javascript
angular
  .module('hoge')
  .service('hogeService', function(){
    this.func1 = function(){}:
    this.func2 = function(){}:
    this.func3 = function(){}:
  });
```

# javascirptの new演算子の有無に着目したオブジェクト生成 <a id="orgheadline2"></a>
javascriptではnew演算子を使うことを前提とした関数名の先頭を大文字にする慣習があるようなので、本記事でもそれに倣います。Person関数がnewを使う関数でperson関数がnewを使わない関数です

```javascript
function Person(name, age){
  this.name = name;
  this.age = age;
  this.introduce = function(){ console.log(this.name + 'です。' +  this.age + '才です。'); };
  this.jump = function(){ console.log('ぴょーん'); };
  this.eat = function(){ console.log('ぱっくん'); };
}

var taro = new Person('太郎', 10);
taro.introduce();
taro.eat();
taro.jump();
```

本記事は、Angularのサービスとファクトリの説明を趣旨としています。 new演算子でPersonインタンスを作るたびに、introduceやjump, eat関数オブジェクトが生成されてしまう良くない例ではあります。 しかし、Angularのサービスはシングルトンという前提があり、説明の都合でよくない例ではあるのですがここではこうしておきます。

```javascript
function person(name, age){
  var object = {};
  object.name = name;
  object.age = age;
  object.introduce = function(){ console.log(this.name + 'です。' +  this.age + '才です。'); };
  object.jump = function(){ console.log('ぴょーん'); };
  object.eat = function(){ console.log('ぱっくん'); };
  return object;
}

var taro = person('太郎', 10);
taro.introduce();
taro.eat();
taro.jump();
```

もう少し変形すると、

```javascript
function person(name, age){
  function introduce(){ console.log(this.name + 'です。' +  this.age + '才です。'); },
  function jump(){ console.log('ぴょーん'); },
  function eat(){ console.log('ぱっくん'); },

  return {
    name: name,
    age: age,
    introduce: introduce,
    jump: jump,
    eat: eat
  };

var taro = person('太郎', 10);
taro.introduce();
taro.eat();
taro.jump();
```

となります。このnew 演算子版と、new 演算子使わない版は、ちょうどAngularのサービスとファクトリの関係に対応しています。

```javascript
angular
  .module('hoge')
  .service('hogeService', function(){
    this.func1 = function(){}:
    this.func2 = function(){}:
    this.func3 = function(){}:
  })
  .factory('hogeFactory', function(){
    function func1 (){}
    function func2 (){}
    function func3 (){}
    return {
      func1: func1,
      func2: func2,
      func3: func3,
    };
  })
;
```

つまりAngularのサービスはインジェクションするときにnew演算子を使いますが、ファクトリはnew演算子を使わないということです。 そして、一般的なjavascriptプログラムとして同じ関数オブジェクトを何度も生成するような悪い書き方とされるコードでも、 Angularのサービスやファクトリはシングルトンなので問題ないということになります。 このあたりのことが分からない人はjavascriptにおけるプロトタイプを学ぶ必要があります。