Partagez le premier article, sur NodeJS - connaissance commune de Javascript et comment passer de développeur Javascript à développeur NodeJS (le framework spécifique ne sera pas présenté). Avant de lire cet article, j'espère que vous avez une première compréhension de javascript.
Javascript est un langage interprété basé sur des modèles prototypes. L'interprétation sera discutée plus tard dans NodeJS. La chaîne de prototypes est l'une des méthodes d'implémentation orientées objet de Javascript avant ES6. Une nouvelle méthode d'implémentation est ajoutée à la classe prise en charge dans ES6. Tout en Javascript est un objet, y compris les « classes ». Ceux qui ont été exposés à la métaprogrammation Ruby/Python peuvent trouver cela très familier, et Javascript peut facilement implémenter une méthode de génération dynamique de classes.
1. "Classe" simple implémentée sur la base d'une chaîne de prototypes
var Person = function(name){ this.name = name; }; Person.staticSay = function(name){ console.log('Hello ' + name); }; Person.prototype.sayHi = function(){ Person.staticSay(this.name); }
Mentionnez certaines spécifications courantes, par exemple, toutes les méthodes en Javascript sont nommées en casse chameau, les guillemets simples sont préférés, deux espaces sont utilisés, etc. Pour plus de spécifications, veuillez vous référer à https://github.com /airbnb/ javascript.
staticSay dans le code est une méthode statique, c'est-à-dire qu'elle ne peut être appelée que via Person.staticSay. Lorsque la personne ci-dessus génère une instance, par exemple var vincent = new Person('vincent');, vincent héritera automatiquement de toutes les méthodes de Person.prototype (cela dans le code fait référence au contexte actuel, qui est le vincent ci-dessus) .
Parallèlement, vous pouvez également ajouter dynamiquement des méthodes à l'objet vincent, comme le code suivant :
var vincent = new Person('vincent') vincent.tellName = function(){ console.log('Hi, i\'m am' + this.name) };
Ensuite, lorsque vous avez besoin de simuler l'héritage, vous devez travailler sur un prototype. Par exemple, Worker.prototype = new Person() est utilisé ci-dessous pour y parvenir. Toutes les méthodes et propriétés de l'objet instance renvoyées par new Person() sont affectées au prototype, simulant l'héritage déguisé. Cette méthode recherche finalement le contenu du prototype couche par couche (car les méthodes de chaque instance sont dans le prototype, en remontant jusqu'à Objet). Bien entendu, vous pouvez également simuler l'héritage en attribuant des valeurs au prototype via une traversée.
2. Changement de contexte
L'expression la plus intuitive du contexte est celle du bloc de code, qui est généralement utilisé dans la programmation orientée objet pour faire référence à l'instance correspondante générée par la "classe" actuelle, qui est cohérente avec self dans d'autres langages.
En continuant à utiliser l'exemple ci-dessus, une méthode Person.prototype.sayHi a été implémentée ci-dessus. Maintenant j'ai un nouvel objet, le code est le suivant :
var Cat = function(name){ this.name = name; } var c = new Cat('tomcat');
Et si un jour j'avais envie que le chat se présente comme un être humain ? Il n'a pas la méthode sayHi. Mais vous pouvez obtenir la méthode humaine sayHi via console.log(Person.prototype.sayHi). Comment les chats peuvent-ils également l'utiliser ?
Javascript a deux méthodes, call et apply. La différence entre elles est que les paramètres sont différents (recherchez-le vous-même) et leur fonction est de changer de contexte. Pour faire simple, vous pouvez changer cela dans la fonction Person.prototype.sayHi en d'autres objets. Utilisation : Personne.prototype.sayHi.call(c).
Est-ce pratique ? Par exemple, le scénario suivant :
var doSomething = function(){ var persons = arguments; };
Dans la fonction ci-dessus, tous les paramètres sont obtenus via les arguments de mots-clés pour prendre en charge un nombre indéfini de paramètres. Nous voulons maintenant utiliser certaines méthodes qui appartiennent à l'origine au type Array sur des personnes. Comment y parvenir ? Ici, vous pouvez utiliser le changement de contexte :
var doSomething = function(){ var persons = arguments; // 使用 Array 的 slice 方法,将 arguments 对象转变为 Array 实例 var persons_arr = Array.prototype.slice.call(arguments); };
3. Clôture
Commençons par un code commun
for (var i = 0; i < 3; i ++){ setTimeout(function(){ console.log(i); }, i) }
Quel sera le résultat de cela ? Sortie 0 1 2 en séquence ? La situation réelle est que lorsque setTimeout exécute le rappel pour la première fois, la boucle for est terminée, ce qui signifie que i vaut déjà 3 à ce moment-là, ce qui donne au résultat final la valeur 3 3 3.
Lorsque vous devez protéger une variable afin qu'elle ne soit pas affectée par le code environnant, vous devrez peut-être envisager une fermeture - un bloc de code avec une portée fermée.
for (var i = 0; i < 3; i ++){ +function(i){ setTimeout(function(){ console.log(i); }, i) }(i) }
Hé, à quoi ça sert ? S'il existe un autre moyen d'y parvenir, veuillez le rechercher vous-même sur Google. La portée de i dans la fermeture est une portée fermée, donc en fin de compte, i dans la fermeture n'a pas été modifié par une exécution externe, donc 0 1 2 peut être généré avec succès.
Brève introduction à certaines fonctionnalités de javascript, chaîne de prototypes de mots-clés, appel et candidature et mots-clés arguments. Pour plus de suggestions, vous pouvez lire des livres tels que le guide faisant autorité, ou comprendre rapidement les types de base et les caractéristiques de chaque type. méthode. Il existe des codes plus magiques, tels que l'obtention de la chaîne du code actuel, puis son traitement pour obtenir le contenu souhaité, l'utilisation de getters et de setters pour effectuer certaines opérations spéciales lorsque l'utilisateur obtient ou attribue des valeurs aux propriétés de l'objet, etc.
4. La différence entre le développement NodeJS et Javascript
Cette section présente principalement les connaissances de base du chargement requis. Tout d'abord, introduisez du code :
// 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
Que se passe-t-il lorsque nous exécutons le nœud c.js ?
require est le mot-clé nodes. Bien que NodeJS soit réputé pour être asynchrone, son require est bloquant. Sinon, il y aura une situation où le code suivant aura déjà commencé à être exécuté avant que les autres modules n'aient été chargés.
La méthode require.resolve() est utilisée pour connaître le chemin réel du fichier que vous référencez. Après l'avoir découvert, Nodejs recherchera dans require.cache pour voir s'il y a un cache. Sinon, il lira le. et analysez-le, donc généralement Dans ce cas, le code exécuté dans un fichier js ne sera exécuté que la première fois qu'il est requis. (astuce. require.cache peut être supprimé manuellement si nécessaire, puis il peut être exécuté plusieurs fois dans une certaine mesure)
Lorsque b.js commence à s'exécuter, il doit d'abord charger a.js. module.exports indique à Nodejs ce que ce fichier est exposé au monde extérieur. Par exemple, a.js expose un objet, y compris l'attribut name et le. méthode doSomething. Ensuite, la variable a dans b.js est en fait cet objet.
Après avoir exécuté pour obtenir a.js, continuez à revenir à b.js. global.a_name équivaut à déclarer une variable globale Cela a un effet similaire à window.a_name = a.name dans le front-end.
Le processus final est terminé et c.js exécute la valeur de sortie.
5. Le principe sous-jacent de l'asynchrone
NodeJS peut facilement donner aux gens une illusion d'utilisation, c'est-à-dire que même après l'avoir écrit pendant une longue période, vous ne savez peut-être pas comment l'asynchrone sous-jacent est implémenté. (La compréhension suivante vient principalement de la compréhension d'asyncio dans python3.4. S'il y a des erreurs, veuillez les signaler).
La libev sous-jacente de NodeJS utilise IOCP sous Windows et libeio basée sur AIO sous *nix pour réaliser une implémentation asynchrone. Grâce à la technologie au niveau du système, un objectif est finalement atteint, c'est-à-dire que l'application lance une requête asynchrone. Enfin, une fois l'exécution terminée, le système informe l'application que le traitement est terminé. Au cours de ce processus, l'application peut suspendre/pousser le traitement précédent dans le pool de threads pour attendre l'exécution, et l'application peut effectuer d'autres tâches pendant cette période.
L'ensemble de l'opération fonctionne via la boucle d'événements au niveau du système. Par exemple, Python fournit des méthodes similaires à run_until et run_forever pour garantir que le programme ne se terminera pas avant une exécution asynchrone. Considérez l'ensemble de l'opération asynchrone comme un atelier qui fonctionne toujours. Les machines de l'atelier sont chargées de vérifier les colis et de les tamponner. Les ouvriers reçoivent un colis, le mettent avec l'étiquette correspondante et le renvoient ensuite à l'atelier. il est transformé. L'ouvrier effectue l'étape suivante de transformation en fonction de l'étiquette qu'il a préalablement apposée sur le colis et de l'étiquette apposée par l'atelier. L'ouvrier n'a pas besoin d'attendre que le colis soit inspecté avant de passer au suivant. Il lui suffit d'accepter un traitement simple et de le déposer ensuite dans l'atelier pour inspection. Il attend ensuite que l'atelier lui rende un colis à une certaine heure, puis passe à l'étape suivante.
À l'heure actuelle, nous n'introduisons principalement que quelques connaissances au niveau linguistique, mais seules celles-ci sont encore loin du développement d'un site Web complet, qui sera introduit plus tard. Y compris Redis, Nginx, pilote de test, etc.
Ce qui précède représente l’intégralité du contenu de cet article, j’espère que vous l’aimerez tous.