通过JavaScript中的函数属性进行依赖注入





一种众所周知但不太流行的依赖项注入方法。尝试在流行的DI npm软件包中实现此方法。另一个DI。



关于OOP和DI的几句话



我想抛弃将OOP反对其他范式的话题。在我看来,不同的范式很可能在一个应用程序中组合在一起。我认为ES类朝着使用OOP的js的吸引力迈出了一大步。



个人经历的一个小故事。在2006年,PERL语言比现在更加流行。他很灵活。那年,我写我的OO实现,和一个小应用程序,Perl语言允许的话,一对夫妇手册的12,和无限的可能性。

2 , , , . , . . , .



JavaScript, , . , , .



TypeScript , , - ( ). .



, JS , . JQuery UI Widget Factory. , - , . ES6 classes ES5 . ES6 DI.



(dependency injection) . , , . , DI, .



DI . , — . , (/ , , , , ...). / . , “”, - . — ! DI.



DI — .





— , . Javascript . . , .



.



App ,



Storage — ( singleton/service),



Date, ( ).



- . (transient) “new”.



- (singleton) “one”.





class App {

    /** @type { function( int ):IDate } */
    newDate;

    /** @type { function(): IStorage } */
    oneStorage;

    construct( newDate, oneStorage ) {
        this.newDate = newDate;
        this.oneStorage = oneStorage;
    }

    main() {
        const oDate1 = this.newDate( 0 );
        const oDate2 = this.newDate( 1000 );
        const oStorage = this.oneStorage();
        oStorage.insert( oDate1.format() + ' - ' + oDate2.format() );
    }
}


, . (lazy). , ( inversify: to, toSelf, toConstantValue, toDynamicValue, toConstructor, toFactory, toFunction, toAutoFactory, toProvider, toService), DI . , .



DI . DI , , . DI .





dependency injection



, , , . dependency injection. :



  1. , . .
  2. , / . , , .
  3. , . , , , , / IDE.


DI. , DI , .



DI . , . , , DI .



, , , , , . , - , - , . . — “-” )





dependency injection javascript/typescript



, “di” npm. ~1400. . npm dependents.





repo npm dependents npm weekly downloads github stars , , lang ES classes interfaces inject property bundle size, KB open github issues github forks
inversify/Inversifyjs

1798

408k 6.6k 6 1 TS + + + 63.3 204 458
typestack/typedi 353 62k 1.9k 5 3 TS + + + 30.3 17 98
thlorenz/proxyquire 344 426k 2.6k 8 8 ES5 ? ? ? ? 9 116
jeffijoe/awilix 244 42k 1.7k 5 1 TS + - - 31.7 2 92
aurelia/dependency-injection

153

13k 156 6 2 TS + - ? ? 2 68
stampit-org/stampit 170

22k 3k 8 1 ES5 ? ? ? ? 6 107
microsoft/tsyringe

149

80k 1.5k 3 1 TS + + - 30.4 27 69
boblauer/mock-require

136 160k 441 6 1 ES5 ? ? ? ? 4 29
mgechev/injection-js 105 236k 928 4 1 TS + -? ? 41.7 0 48
young-steveo/bottlejs

101

16k 1.2k 6 1 ES5 + D.TS -? - - 13.3 2 63
jaredhanson/electrolyte

33 1k 569 7 1 ES5 - - - ? 25 65
zhang740/power-di

10

0.2k 65 4 1 TS + + + 45.0 2 69
jpex-js/vue-inject

9 0.8k 174 4 12 ES5 - - ? ? 3 14
zazoomauro/node-dependency-injection

5

1k 123 4 2 ES6 + D.TS + -? + 291.0 3 17
justmoon/constitute 4 8k 132 5 60 ES6 + -? - 56.2 4 6
owja/ioc 1

2k 158 1 3 TS + + + 11.3 4 5
kraut-dps/di-box

1 0k 0 0 1 ES6 + D.TS + + + 11.1 0 0




Gitcompare



Codesandbox





https://github.com/inversify/InversifyJS



, , , . )). , . )





https://github.com/typestack/typedi



, , . , , App Date, . , ?





https://github.com/thlorenz/proxyquire



, . . DI, .





https://github.com/jeffijoe/awilix



, “Symbol(Symbol.toPrimitive)”, , - Proxy, Date . .





https://github.com/aurelia/dependency-injection



. Aurelia.





https://github.com/stampit-org/stampit



. . - .





https://github.com/microsoft/tsyringe



Microsoft, . , .





https://github.com/boblauer/mock-require



proxyquire.





https://github.com/mgechev/injection-js



Angular 4. , , useFactory .





https://github.com/young-steveo/bottlejs



. .instanceFactory, .





https://github.com/jaredhanson/electrolyte



. ES6 .





https://github.com/zhang740/power-di



. React. . - . , .





https://github.com/jpex-js/vue-inject



vue ES6 . . ES6 classes, provide inject DI. .





https://github.com/zazoomauro/node-dependency-injection



YAML/JS/JSON . . php symfony , setParameter, , .





https://github.com/justmoon/constitute



, , DI .





https://github.com/owja/ioc



inversify, . , : , , . , .





https://github.com/kraut-dps/di-box



, .





, , DI , , .







“”, :





class Service {
    work () {
        console.log('work');
    }
}

class App {
    oneService;
    main () {
        this.oneService().work();
    }
}

//  es6 ,   DI
class AppBox {
    Service;
    App;

    _oService;

    newApp () {
        const oApp = new this.App();

        //   
        oApp.oneService = this.oneService.bind(this);

        return oApp;
    }

    oneService () {
        if (!this._oService) {
            this._oService = new this.Service();
        }
        return this._oService;
    }
}

const oBox = new AppBox();
oBox.Service = Service;
oBox.App = App;
const oApp = oBox.newApp();
oApp.main();


Box , , .

(.one()), bind(this), . :





import {Box} from "di-box";

class Service {
    work() {
        console.log( 'work' );
    }
}

class App {
    oneService;
    main() {
        this.oneService().work();
    }
}

class AppBox extends Box {
    App;
    Service;

    newService() {
        return new this.Service();
    }

    oneService() {
        return this.one( this.newService );
    }

    newApp() {
        const oApp = new this.App();
        oApp.oneService = this.oneService;
        return oApp;
    }
}

const oBox = new AppBox();
oBox.Service = Service;
oBox.App = App;
const oApp = oBox.newApp();
oApp.main();


codesandbox





:



const oBox = new AppBox();
//  oBox.Service = Service;
oBox.App = App;
const oApp = oBox.newApp(); //   :  Service is undefined
oApp.main();


...



DI . , , . , .

:





constructor( arg1, arg2, arg3 ) {}

// 

constructor( { arg1key: arg1, arg2key: arg2, arg3key: arg3 } ) {}


, . ?



  1. - .
  2. .


ES . , - . DI .



. undefined. . .



:





class A {
    _arg1;
    _arg2;

    constructor( arg1, arg2 = null ) {
        this._arg1 = arg1;
        this._arg2 = arg2;
    }
}
const instance = new A( 1, 2 );

// 

class A {
    arg1; //  ,   
    arg2 = null; //    null !== undefined
}
const instance = new A();
instance.arg1 = 1;
instance.arg2 = 2;


dependency injection , . di-box.

typescript constructor( public arg1: type, public arg2: type ) Box:



new AppBox( { bNeedSelfCheck: false, sNeedCheckPrefix: null } );


codesandbox.



因此,使用di-box,我们有机会以最少,但足够的实现DI的附加代码以OOP风格进行编写。一方面,在实现中存在原型“魔术”,但另一方面,它仅在元级别,并且组件本身可以是纯净的,对环境一无所知。



我很乐意讨论它,也许我错过了其他一些图书馆。或者,也许您知道如何在某些DI实现中最好地实现我的示例。在评论中写。




All Articles