Kongsi artikel pertama, tentang NodeJS - pengetahuan umum tentang Javascript dan cara beralih daripada pembangun Javascript kepada pembangun NodeJS (rangka kerja khusus tidak akan diperkenalkan). Sebelum membaca artikel ini, saya harap anda mempunyai pemahaman awal tentang javascript.
Javascript ialah bahasa yang ditafsirkan berdasarkan model prototaip. Tafsiran akan dibincangkan kemudian dalam NodeJS Rantaian prototaip adalah salah satu kaedah pelaksanaan berorientasikan objek bagi ES6. Kaedah pelaksanaan baharu ditambahkan pada kelas yang disokong dalam ES6. Segala-galanya dalam Javascript adalah objek, termasuk "kelas". Mereka yang telah terdedah kepada metaprogramming ruby/python mungkin mendapati ini sangat biasa, dan Javascript boleh dengan mudah melaksanakan kaedah menjana kelas secara dinamik.
1. "Kelas" mudah dilaksanakan berdasarkan rantaian prototaip
var Person = function(name){ this.name = name; }; Person.staticSay = function(name){ console.log('Hello ' + name); }; Person.prototype.sayHi = function(){ Person.staticSay(this.name); }
Sebutkan beberapa spesifikasi biasa, contohnya, semua kaedah dalam Javascript dinamakan dalam kotak unta, petikan tunggal diutamakan, dua ruang digunakan, dsb. Untuk spesifikasi lanjut, sila rujuk https://github.com /airbnb/ javascript.
staticSay dalam kod adalah kaedah statik, iaitu, ia hanya boleh dipanggil melalui Person.staticSay. Apabila Orang di atas menjana contoh, sebagai contoh, var vincent = new Person('vincent');, vincent akan secara automatik mewarisi semua kaedah Person.prototype (ini dalam kod merujuk kepada konteks semasa, iaitu vincent di atas) .
Pada masa yang sama, anda juga boleh menambahkan kaedah secara dinamik pada objek vincent, seperti kod berikut:
var vincent = new Person('vincent') vincent.tellName = function(){ console.log('Hi, i\'m am' + this.name) };
Kemudian apabila anda perlu mensimulasikan warisan, anda perlu mengusahakan prototaip. Sebagai contoh, Worker.prototype = new Person() digunakan di bawah untuk mencapai ini Semua kaedah dan sifat objek contoh yang dikembalikan oleh Person() baharu diberikan kepada prototaip, mensimulasikan warisan dalam penyamaran. Kaedah ini akhirnya mencari kandungan prototaip lapisan demi lapisan (kerana kaedah setiap contoh adalah dalam prototaip, naik ke Objek). Sudah tentu, anda juga boleh mensimulasikan warisan dengan memberikan nilai kepada prototaip melalui traversal.
2. Penukaran konteks
Ungkapan konteks yang paling intuitif ialah ini dalam blok kod, yang biasanya digunakan dalam pengaturcaraan berorientasikan objek untuk merujuk kepada contoh sepadan yang dijana oleh "kelas" semasa, yang konsisten dengan diri dalam bahasa lain.
Terus menggunakan contoh di atas, kaedah Person.prototype.sayHi telah dilaksanakan di atas Sekarang saya mempunyai objek baharu, kodnya adalah seperti berikut:
var Cat = function(name){ this.name = name; } var c = new Cat('tomcat');
Bagaimana jika suatu hari saya tiba-tiba mahu kucing itu memperkenalkan dirinya seperti manusia dia tidak mempunyai kaedah sayHi. Tetapi anda boleh mendapatkan kaedah sayHi manusia melalui console.log(Person.prototype.sayHi Bagaimana kucing juga boleh menggunakannya?
Javascript mempunyai dua kaedah, panggil dan gunakan Perbezaan antaranya ialah parameternya berbeza (Google sendiri), dan fungsinya adalah untuk menukar konteks. Ringkasnya, anda boleh menukar ini dalam fungsi Person.prototype.sayHi kepada objek lain. Penggunaan: Person.prototype.sayHi.call(c).
Adakah ini praktikal? Contohnya, senario berikut:
var doSomething = function(){ var persons = arguments; };
Dalam fungsi di atas, semua parameter diperoleh melalui argumen kata kunci untuk menyokong bilangan parameter yang tidak ditentukan. Sekarang kita mahu menggunakan beberapa kaedah yang pada asalnya tergolong dalam jenis Array pada orang Bagaimana untuk mencapai ini? Di sini anda boleh menggunakan penukaran konteks:
var doSomething = function(){ var persons = arguments; // 使用 Array 的 slice 方法,将 arguments 对象转变为 Array 实例 var persons_arr = Array.prototype.slice.call(arguments); };
3. Penutupan
Mari mulakan dengan beberapa kod biasa
for (var i = 0; i < 3; i ++){ setTimeout(function(){ console.log(i); }, i) }
Apakah hasil daripada ini? Output 0 1 2 dalam urutan? Situasi sebenar ialah apabila setTimeout melaksanakan panggilan balik buat kali pertama, gelung for telah tamat, yang bermaksud bahawa i sudah 3 pada masa ini, menyebabkan hasil keluaran akhir ialah 3 3 3.
Apabila anda perlu melindungi pembolehubah supaya ia tidak terjejas oleh kod sekeliling, anda mungkin perlu mempertimbangkan penutupan - blok kod dengan skop tertutup.
for (var i = 0; i < 3; i ++){ +function(i){ setTimeout(function(){ console.log(i); }, i) }(i) }
Hei, untuk apa? Jika ada cara lain untuk mencapainya, sila Google sendiri. Skop i dalam penutupan adalah skop tertutup, jadi pada akhirnya, i dalam penutupan tidak diubah oleh pelaksanaan luaran, jadi 0 1 2 boleh berjaya dikeluarkan.
Pengenalan ringkas kepada beberapa ciri javascript, rantai prototaip kata kunci, panggil dan gunakan, dan kata kunci hujah Untuk mendapatkan cadangan lanjut, anda boleh membaca buku seperti panduan berwibawa, atau memahami dengan cepat jenis asas dan ciri setiap jenis. kaedah. Terdapat beberapa lagi kod ajaib, seperti mendapatkan rentetan kod semasa, dan kemudian memprosesnya untuk mendapatkan kandungan yang anda inginkan, menggunakan getter dan setter untuk melakukan beberapa operasi khas apabila pengguna mendapat atau memberikan nilai kepada sifat objek, dll.
4. Perbezaan antara pembangunan NodeJS dan Javascript
Bahagian ini terutamanya memperkenalkan pengetahuan asas tentang memerlukan pemuatan Pertama, perkenalkan beberapa kod:
// a.js module.exports = { name: "a", doSomething: function(){ return "something"; } } // b.js var a = require('./a') global.a_name = a.name; // c.js require('./b'); console.log(a_name) // 执行后打印 a
Was passiert, wenn wir Knoten c.js ausführen?
require ist das Node-Schlüsselwort. Obwohl NodeJS dafür bekannt ist, asynchron zu sein, blockiert es. Andernfalls kann es vorkommen, dass die Ausführung des folgenden Codes bereits begonnen hat, bevor andere Module geladen wurden.
Die Methode require.resolve() wird verwendet, um den tatsächlichen Pfad der Datei herauszufinden, auf die Sie verweisen. Nachdem Sie dies herausgefunden haben, prüft Nodejs, ob ein Cache vorhanden ist Datei und analysieren Sie sie. In diesem Fall wird der ausgeführte Code in einer js-Datei normalerweise nur dann ausgeführt, wenn er zum ersten Mal benötigt wird. (Tipp. require.cache kann bei Bedarf manuell gelöscht und dann bis zu einem gewissen Grad mehrmals ausgeführt werden)
Wenn b.js mit der Ausführung beginnt, muss es zuerst a.js laden. module.exports teilt Nodejs mit, was diese Datei der Außenwelt zugänglich macht. Beispielsweise macht a.js ein Objekt verfügbar, einschließlich des Namensattributs und des doSomething-Methode. Dann ist die Variable a in b.js tatsächlich dieses Objekt.
Nachdem Sie a.js ausgeführt haben, kehren Sie weiterhin zu b.js zurück. Global.a_name entspricht der Deklaration einer globalen Variablen. Dies hat einen ähnlichen Effekt wie window.a_name = a.name im Frontend.
Der letzte Prozess ist abgeschlossen und c.js führt den Ausgabewert aus.
5. Das zugrunde liegende Prinzip der Asynchronität
NodeJS kann den Leuten leicht eine Illusion der Verwendung vermitteln, das heißt, selbst nach längerem Schreiben wissen Sie möglicherweise nicht, wie die zugrunde liegende Asynchronität implementiert ist. (Das folgende Verständnis stammt hauptsächlich aus dem Verständnis von Asyncio in Python3.4. Wenn Fehler auftreten, weisen Sie bitte darauf hin.)
Das zugrunde liegende Libev von NodeJS verwendet IOCP unter Windows und AIO-basiertes Libeio unter *nix, um eine asynchrone Implementierung zu erreichen. Durch die Technologie auf Systemebene wird schließlich ein Ziel erreicht: Die Anwendung initiiert eine asynchrone Anforderung. Nachdem das System die Ausführung abgeschlossen hat, benachrichtigt das System die Anwendung schließlich über den Abschluss der Verarbeitung. Während dieses Prozesses kann die Anwendung die vorherige Verarbeitung anhalten/in den Thread-Pool verschieben, um auf die Ausführung zu warten, und die Anwendung kann in diesem Zeitraum andere Aufgaben ausführen.
Der gesamte Vorgang läuft über die Ereignisschleife auf Systemebene ab. Python bietet beispielsweise ähnliche Methoden wie run_until und run_forever, um sicherzustellen, dass das Programm nicht vor der asynchronen Ausführung beendet wird. Stellen Sie sich den gesamten asynchronen Betrieb als eine Werkstatt vor, die ständig in Betrieb ist. Die Maschinen in der Werkstatt sind dafür verantwortlich, die Pakete zu überprüfen und zu stempeln. Die Arbeiter nehmen ein Paket entgegen, legen es mit dem entsprechenden Etikett ab und bringen es anschließend in die Werkstatt zurück Die Bearbeitung erfolgt durch den Werker anhand des zuvor auf dem Paket angebrachten Etiketts und des von der Werkstatt angebrachten Etiketts. Der Arbeiter muss nicht auf die Inspektion des Pakets warten, bevor er mit dem nächsten fortfährt. Er muss lediglich die einfache Bearbeitung entgegennehmen und sie dann zur Inspektion in die Werkstatt bringen. Anschließend wartet er darauf, dass ihm die Werkstatt zu einem bestimmten Zeitpunkt ein Paket zurückgibt, und fährt dann mit dem nächsten Schritt fort.
Derzeit führen wir hauptsächlich nur einige Sprachkenntnisse ein, aber nur diese sind noch weit von der Entwicklung eines vollständigen Webs entfernt, das später eingeführt wird. Einschließlich Redis, Nginx, Testtreiber usw.
Das Obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, er gefällt Ihnen allen.