[javascript] 反射與依賴注入!,javascript注入

來源:互聯網
上載者:User

[javascript] 反射與依賴注入!,javascript注入

對於javascript中的反射的理解,一直都是認為,利用數組對回呼函數進行儲存,之後在適當的時刻利用call或是apply 方法,對回調進行調用即可,一般如下操作:

首先定義兩個方法:

var service = function() {    return { name: 'Service' };}var router = function() {    return { name: 'Router' };}

我們有另一個函數需要用到這兩個模組。

var doSomething = function(other) {    var s = service();    var r = router();};

當然,我們希望能夠能夠使用依賴注入的方式去做,把該控制權交給電腦去做,而不是人為的去調用如下:

var doSomething = injector.resolve('router,,service', function(a, b, c) {    expect(a().name).to.be('Router');    expect(b).to.be('Other');    expect(c().name).to.be('Service');});doSomething("Other");

那麼我們可以造出一個反射方法如下:

var injector ={dependencies: {},    register: function(key, value) {        this.dependencies[key] = value;    },resolve:function(deps, func, scope) {    var args = [];for(var i=0; i<deps.length, d=deps[i]; i++) {if(this.dependencies[d]) {args.push(this.dependencies[d]);} else {throw new Error('Can\'t resolve ' + d);}}return function() {func.apply(scope || {}, args.concat(Array.prototype.slice.call(arguments, 0)));}}};

如上代碼,dependencies 用來儲存回呼函數集合,resolve用來調用。

這也算是一個比較成熟ok的想法。

但是依舊存在幾點問題:

1 resolve 在進行調用時,deps參數列表順序必須保持一致。

2 這一點有點牽強,但是也算。在調用時,需要再一次的輸入形參,而不能直接調用。


那麼為瞭解決以上問題,給出以下解決方案:

var injector ={dependencies: {},register: function(key, value) {this.dependencies[key] = value;},resolve: function() {var func, deps, scope, args = [], self = this;if(typeof arguments[0] === 'string') {func = arguments[1];deps = arguments[0].replace(/ /g, '').split(',');scope = arguments[2] || {};} else {func = arguments[0];deps = func.toString().match(/^function\s*[^\(]*\(\s*([^\)]*)\)/m)[1].replace(/ /g, '').split(',');scope = arguments[1] || {};}return function() {var a = Array.prototype.slice.call(arguments, 0);for(var i=0; i<deps.length; i++) {var d = deps[i];args.push(self.dependencies[d] && d != '' ? self.dependencies[d] : a.shift());}func.apply(scope || {}, args);}}};

利用正則對代碼進行解析,解析出function 列表參數,再進行一一自動匹配傳值,那麼即可解決,順序必須一直問題,當然這也是當然最熱mvvm架構AngularJs採取的方式。

調用方式可以如下:

injector.resolve(['service,,router', function(service, router) {}]);

你可能注意到在第一個參數後面有兩個逗號——注意

這不是筆誤。空值實際上代表“Other”參數(預留位置)。這顯示了我們是如何控制參數順序的。


最後還有一種方式,直接注入scope ,也就是直接注入範圍,那麼範圍被注入,也就不存在上述的傳參順序問題

因為不在需要傳遞參數,直接可以從範圍中訪問到。

 var injector = {    dependencies: {},    register: function(key, value) {        this.dependencies[key] = value;    },    resolve: function(deps, func, scope) {        var args = [];        scope = scope || {};        for(var i=0; i<deps.length, d=deps[i]; i++) {            if(this.dependencies[d]) {                scope[d] = this.dependencies[d];            } else {                throw new Error('Can\'t resolve ' + d);            }        }        return function() {            func.apply(scope || {}, Array.prototype.slice.call(arguments, 0));        }            }}

var doSomething = injector.resolve(['service', 'router'], function(other) {    expect(this.service().name).to.be('Service');    expect(this.router().name).to.be('Router');    expect(other).to.be('Other');});doSomething("Other");


javascript反射依賴注入新的理解,記錄之,謹防忘記.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.