Rumah  >  Artikel  >  hujung hadapan web  >  Penjelasan terperinci tentang suntikan pergantungan dalam kemahiran JavaScript_javascript

Penjelasan terperinci tentang suntikan pergantungan dalam kemahiran JavaScript_javascript

WBOY
WBOYasal
2016-05-16 16:08:511063semak imbas

Dunia pengaturcaraan komputer sebenarnya adalah proses mengabstraksi bahagian mudah secara berterusan dan menyusun abstraksi ini. JavaScript tidak terkecuali Apabila kita menggunakan JavaScript untuk menulis aplikasi, adakah kita semua menggunakan kod yang ditulis oleh orang lain, seperti beberapa perpustakaan atau rangka kerja sumber terbuka yang terkenal. Apabila projek kami berkembang, semakin banyak modul yang perlu kami andalkan menjadi semakin penting Pada masa ini, cara mengatur modul ini dengan berkesan telah menjadi isu yang sangat penting. Suntikan kebergantungan menyelesaikan masalah tentang cara mengatur modul bergantung kod dengan berkesan. Anda mungkin pernah mendengar istilah "suntikan kebergantungan" dalam beberapa rangka kerja atau perpustakaan, seperti rangka kerja hadapan yang terkenal AngularJS Suntikan Ketergantungan ialah salah satu ciri yang sangat penting. Walau bagaimanapun, suntikan ketergantungan bukanlah perkara baru sama sekali Ia telah wujud dalam bahasa pengaturcaraan lain seperti PHP untuk masa yang lama. Pada masa yang sama, suntikan pergantungan tidaklah sesulit yang dibayangkan. Dalam artikel ini, kita akan mempelajari konsep suntikan pergantungan dalam JavaScript dan menerangkan dengan cara yang mudah dan mudah cara menulis kod "gaya suntikan pergantungan".

Penetapan Matlamat

Andaikan kita kini mempunyai dua modul. Modul pertama digunakan untuk menghantar permintaan Ajax, manakala modul kedua digunakan sebagai penghala.

Salin kod Kod adalah seperti berikut:

var service = function() {
Kembalikan { nama: 'Perkhidmatan' };
}
var penghala = function() {
Kembalikan { nama: 'Penghala' };
}

Pada masa ini, kami menulis fungsi yang memerlukan penggunaan dua modul yang disebutkan di atas:
Salin kod Kod adalah seperti berikut:

var doSomething = function(other) {
var s = perkhidmatan();
var r = penghala();
};

Di sini, untuk menjadikan kod kami lebih menarik, parameter ini perlu menerima beberapa lagi parameter. Sudah tentu, kita boleh menggunakan sepenuhnya kod di atas, tetapi kod di atas sedikit kurang fleksibel dari sebarang aspek. Bagaimana jika nama modul yang kita perlukan untuk menggunakan perubahan kepada ServiceXML atau ServiceJSON? Atau bagaimana jika kita ingin menggunakan beberapa modul palsu untuk tujuan ujian. Pada ketika ini, kita tidak boleh hanya mengedit fungsi itu sendiri. Jadi perkara pertama yang perlu kita lakukan ialah lulus modul bergantung sebagai parameter kepada fungsi, kodnya adalah seperti berikut:
Salin kod Kod adalah seperti berikut:

var doSomething = fungsi(perkhidmatan, penghala, lain-lain) {
var s = perkhidmatan();
var r = penghala();
};

Dalam kod di atas, kami lulus tepat modul yang kami perlukan. Tetapi ini membawa masalah baru. Katakan kita memanggil kaedah doSomething dalam kedua-dua bahagian kod. Pada ketika ini, bagaimana jika kita memerlukan pergantungan ketiga. Pada masa ini, bukan idea yang bijak untuk mengedit semua kod panggilan fungsi. Oleh itu, kami memerlukan sekeping kod untuk membantu kami melakukan ini. Inilah masalah yang cuba diselesaikan oleh penyuntik kebergantungan. Kini kami boleh menetapkan matlamat kami:

1. Kita sepatutnya boleh mendaftar tanggungan
2. Penyuntik kebergantungan harus menerima fungsi dan kemudian mengembalikan fungsi yang boleh mendapatkan sumber yang diperlukan
3. Kod tidak boleh rumit, tetapi harus ringkas dan mesra
4. Penyuntik kebergantungan harus mengekalkan skop fungsi yang diluluskan
5. Fungsi yang diluluskan seharusnya boleh menerima parameter tersuai, bukan hanya kebergantungan yang diterangkan

memerlukan kaedah/kaedah AMD

Mungkin anda pernah mendengar tentang requirejs yang terkenal, iaitu perpustakaan yang boleh menyelesaikan masalah suntikan pergantungan dengan baik:

Salin kod Kod adalah seperti berikut:

define(['service', 'router'], function(service, router) { 
// ...
});

Idea requirejs ialah pertama kita harus menerangkan modul yang diperlukan, dan kemudian menulis fungsi anda sendiri. Antaranya, susunan parameter adalah penting. Katakan kita perlu menulis modul yang dipanggil penyuntik yang boleh melaksanakan sintaks yang serupa.
Salin kod Kod adalah seperti berikut:

var doSomething = injector.resolve(['service', 'router'], function(service, router, other) {
Jangkakan(perkhidmatan().nama).menjadi('Perkhidmatan');
Jangkakan(penghala().nama).menjadi('Penghala');
Jangkakan(lain).untuk.jadi('Lain-lain');
});
doSomething("Lain");

Sebelum meneruskan, satu perkara yang perlu dijelaskan ialah dalam badan fungsi doSomething, kami menggunakan perpustakaan penegasan expect.js untuk memastikan ketepatan kod. Terdapat sesuatu yang serupa dengan idea TDD (Test Driven Development) di sini.

Kini kami secara rasmi mula menulis modul penyuntik kami. Mula-mula ia mestilah monolit supaya ia mempunyai fungsi yang sama dalam setiap bahagian aplikasi kami.

Salin kod Kod adalah seperti berikut:

penyuntik var = {
tanggungan: {},
Daftar: fungsi(kunci, nilai) {
This.dependencies[key] = value;
},
Selesaikan: fungsi(deps, func, skop) {

}
}


Objek ini sangat mudah, mengandungi hanya dua fungsi dan pembolehubah untuk tujuan penyimpanan. Apa yang perlu kita lakukan ialah menyemak tatasusunan deps dan kemudian mencari jawapan dalam pembolehubah kebergantungan. Bahagian selebihnya ialah menggunakan kaedah .apply untuk memanggil pembolehubah func yang kami lalui:
Salin kod Kod adalah seperti berikut:

menyelesaikan: fungsi(deps, func, skop) {
var args = [];
untuk(var i=0; i            if(this.dependencies[d]) {
               args.push(this.dependencies[d]);
         } lain {
                buang Ralat baharu('Tidak dapat diselesaikan ' d);
}
}
Kembalikan fungsi() {
           func.apply(skop || {}, args.concat(Array.prototype.slice.call(arguments, 0)));
                                             }

Jika anda perlu menentukan skop, kod di atas juga boleh berjalan seperti biasa.

Dalam kod di atas, fungsi Array.prototype.slice.call(arguments, 0) adalah untuk menukar pembolehubah argumen kepada tatasusunan sebenar. Setakat ini, kod kami lulus ujian dengan sempurna. Tetapi masalahnya di sini ialah kita mesti menulis modul yang diperlukan dua kali, dan kita tidak boleh menyusunnya dalam sebarang susunan. Parameter tambahan sentiasa datang selepas semua kebergantungan.

Kaedah refleksi

Menurut penjelasan dalam Wikipedia, refleksi bermaksud objek boleh mengubah suai struktur dan tingkah lakunya sendiri semasa program sedang berjalan. Dalam JavaScript, secara ringkasnya, ia adalah keupayaan untuk membaca kod sumber objek dan menganalisis kod sumber. Masih kembali kepada kaedah doSomething kami, jika anda memanggil kaedah doSomething.toString(), anda boleh mendapatkan rentetan berikut:


Salin kod Kod adalah seperti berikut:
"fungsi (perkhidmatan, penghala, lain-lain) {
var s = perkhidmatan();
var r = penghala();
}"

Dengan cara ini, selagi kita menggunakan kaedah ini, kita boleh mendapatkan parameter yang kita inginkan dengan mudah, dan yang lebih penting, nama mereka. Ini juga merupakan kaedah yang digunakan oleh AngularJS untuk melaksanakan suntikan pergantungan. Dalam kod AngularJS, kita boleh melihat ungkapan biasa berikut:

Salin kod Kod adalah seperti berikut:
/^fungsi*[^(]*(s*([^)]*))/m


Kami boleh mengubah suai kaedah penyelesaian kepada kod yang ditunjukkan di bawah:

Salin kod Kod adalah seperti berikut:

selesaikan: function() {
var func, deps, skop, args = [], self = this;
func = hujah[0];
deps = func.toString().match(/^functions*[^(]*(s*([^)]*))/m)[1].replace(/ /g, '').split(' ,');
skop = argumen[1] || {};
Kembalikan fungsi() {
      var a = Array.prototype.slice.call(argumen, 0);
untuk(var i=0; i             var d = deps[i];
                 args.push(self.dependencies[d] && d != '' ? self.dependencies[d] : a.shift());
}
           func.apply(skop || {}, args);
                                             }

Kami menggunakan ungkapan biasa di atas untuk memadankan fungsi yang kami takrifkan dan kami boleh mendapatkan hasil berikut:


Salin kod Kod adalah seperti berikut:
["fungsi (perkhidmatan, penghala, lain-lain)", "perkhidmatan, penghala, lain-lain"]

Pada ketika ini, kita hanya memerlukan item kedua. Tetapi setelah kami mengalih keluar ruang tambahan dan memisahkan rentetan dengan , kami mendapat tatasusunan deps. Kod berikut ialah bahagian yang kami ubah suai:

Salin kod Kod adalah seperti berikut:
var a = Array.prototype.slice.call(arguments, 0);
...
args.push(self.dependencies[d] && d != '' ? self.dependencies[d] : a.shift());

Dalam kod di atas, kami melintasi projek bergantung Jika terdapat projek yang hilang, jika terdapat bahagian yang hilang dalam projek bergantung, kami mendapatkannya daripada objek argumen. Jika tatasusunan kosong, menggunakan kaedah anjakan hanya akan kembali tidak ditentukan tanpa membuang ralat. Setakat ini, versi baharu penyuntik kelihatan seperti ini:


Salin kod Kod adalah seperti berikut:
var doSomething = injector.resolve(function(service, other, router) {
Jangkakan(perkhidmatan().nama).menjadi('Perkhidmatan');
Jangkakan(penghala().nama).menjadi('Penghala');
Jangkakan(lain).untuk.jadi('Lain-lain');
});
doSomething("Lain");

Dalam kod di atas, kami bebas mencampurkan susunan kebergantungan.

Tetapi, tiada yang sempurna. Terdapat masalah yang sangat serius dengan suntikan pergantungan kaedah reflektif. Apabila kod dipermudahkan, ralat berlaku. Ini kerana semasa proses pemudahan kod, nama parameter berubah, yang akan menyebabkan kebergantungan gagal diselesaikan. Contohnya:


Salin kod Kod adalah seperti berikut:
var doSomething=function(e,t,n){var r=e();var i=t()}

Jadi kita memerlukan penyelesaian berikut, sama seperti dalam AngularJS:

Salin kod Kod adalah seperti berikut:
var doSomething = injector.resolve(['service', 'router', function(service, router) {
}]);


Ini sangat serupa dengan penyelesaian AMD yang kami lihat pada mulanya, jadi kami boleh menyepadukan dua kaedah di atas Kod akhir adalah seperti berikut:

Salin kod Kod adalah seperti berikut:

penyuntik var = {
    tanggungan: {},
    daftar: fungsi(kunci, nilai) {
        this.dependencies[key] = value;
    },
    selesaikan: function() {
        var func, deps, skop, args = [], self = this;
        if(jenis argumen[0] === 'rentetan') {
            func = hujah[1];
            deps = argumen[0].replace(/ /g, '').split(',');
            skop = hujah[2] || {};
        } lain {
            func = hujah[0];
            deps = func.toString().match(/^functions*[^(]*(s*([^)]*))/m)[1].replace(/ /g, '').split(' ,');
            skop = hujah[1] || {};
        }
        kembalikan fungsi() {
            var a = Array.prototype.slice.call(arguments, 0);
            untuk(var i=0; i                 var d = deps[i];
                args.push(self.dependencies[d] && d != '' ? self.dependencies[d] : a.shift());
            }
            func.apply(skop || {}, args);
        }       
    }
}

这一个版本的resolve方法可以接受两个或者三个参数。下面是一段测试代码>:

复制代码 代码如下:
var doSomething = injector.resolve('router,,service', function(a,b,c) {
    jangkakan(a().nama).to.be('Router');
    expect(b).to.be('Other');
    jangkakan(c().nama).to.be('Perkhidmatan');
});
doSomething("Lain");

你可能注意到了两个逗号之间什么都没有,这并不是错误。这个空缺是留是是留是是留百这并不是错误.我们控制参数顺序的方法。

结语

在上面的内容中,我们介绍了几种JavaScript中依赖注入的方法,希望本文能够帮助佩作中依赖注入的方法,希望本文能够帮助佩佨丮助你这个技巧,并且写出依赖注入风格的代码。

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn