2

次の例を検討してください。

angular.module('demo')
    .service('MyService', function () {
        this.fn = function () {
            console.log('MyService:fn');
        };
    })
    .factory('MyFactory', function () {
        function fn() {
            console.log('MyFactory:fn');
        }
        return { fn: fn };
    })
    .value('MyValue', {
        fn: function () {
            console.log('MyValue:fn');
        }
    })
    .constant('MyConstant', {
        fn: function () {
            console.log('MyConstant:fn');
        }
    })
    .run(function (MyService, MyFactory, MyValue, MyConstant) {
        MyService.fn();
        MyFactory.fn();
        MyValue.fn();
        MyConstant.fn();

        MyService.fn = undefined;
        MyFactory.fn = undefined;
        MyValue.fn = undefined;
        MyConstant.fn = undefined;
    })
    .run(function (MyService, MyFactory, MyValue, MyConstant) {
        MyService.fn();
        MyFactory.fn();
        MyValue.fn();
        MyConstant.fn();
    });

最初のrun()ログが実行されると、4 つのコンソール ログがすべて実行され、コンソールに何かが出力されます。次に、簡単にするために各プロバイダーfn関数を undefined に設定します。誰かがこの関数をどこかで書き直したとします (これは私が防ぎたいことです)。

2 番目のrun()ブロックでは、すべてが未定義であり、エラーがスローされます。私はこれに混乱しています...少なくともそれらのいくつかconstant最初に思い浮かぶもの)は不変オブジェクトであるべきではありませんか?

これは予想される動作ですか、それとも何か間違っていますか?

4

2 に答える 2

1

関数constant、などを使用するとfactory一度作成され、angular によってキャッシュされ、必要に応じてコンポーネントに挿入されるserviceJavascript オブジェクトを作成できます。これらはJavascriptオブジェクトであるため、(使用の可能性を無視して)コードはこれらのオブジェクトにアクセスでき、実証したようにそれらのプロパティを変更できます。freeze

オブジェクト自体のプロパティは変更できますが、オブジェクト自体を別のオブジェクトに変更することはできません。したがって、すべての改ざんから安全な不変のプロバイダーが本当に必要な場合、私が考えることができる 1 つの方法は、ファクトリを使用することです。オブジェクトではなくゲッター関数を返します。

app.factory('MyFactory', function() {
  var functions = {
    myFunctionName: function() {
    }
  };

  return function(functionName) {
    return functions[functionName];
  };
});

たとえば、コントローラーで次のように使用できます。

app.controller('MyController', function(MyFactory) {
  MyFactory('myFunctionName')();
});

すべてのメソッドを公開し、オブジェクトが変更される可能性を許可する従来の方法よりもこれを使用することの欠点は、単体テストがより複雑になる可能性があることです。ファクトリ メソッドでスパイを簡単に作成することはできません。を使用してcreateSpy(MyFactory, 'myFunctionName')

于 2015-02-01T15:08:28.830 に答える
1

なぜこれは驚きです。Angular は Javascript の上で実行されるフレームワークであり、Javascript は動的言語です。あなたの質問は、実際には言語構造に関するものです。

まず、すべての呼び出しが、最終的には、注入されるオブジェクトを返すプロバイダーを登録していることを認識してください。.service.factory、および.value.provider(.constantは少し異なります) の省略形です。

オブジェクトが注入されると、それらの間に違いがないことが確立されたので、次に気にする必要があるのは、そのオブジェクトを不変にする方法だけです。

Javascript はObject.freeze関数を提供するため、たとえば、次のようにすることができます。

var immutable = {
        fn: function () {
            console.log('MyConstant:fn');
        }
    };
Object.freeze(immutable);

app.constant("MyConstant", immutable);
于 2015-02-01T12:21:00.447 に答える