Maison > interface Web > js tutoriel > Révéler la magie du javascript

Révéler la magie du javascript

Lisa Kudrow
Libérer: 2025-02-21 09:38:10
original
635 Les gens l'ont consulté

Révéler la magie du javascript

Nous utilisons des tonnes d'outils chaque jour. Différentes bibliothèques et cadres font partie de notre travail quotidien. Nous les utilisons parce que nous ne voulons pas réinventer la roue pour chaque projet, même si nous ne comprenons pas ce qui se passe sous le capot. Dans cet article, nous révélerons certains des processus magiques qui se produisent dans les bibliothèques les plus populaires. Nous verrons également si nous pouvons reproduire leur comportement.

Les plats clés

  • Les bibliothèques JavaScript comme jQuery simplifient les manipulations DOM, telles que la création d'éléments à partir de chaînes, en gérant correctement les cas complexes comme les éléments imbriqués.
  • Le système d'injection de dépendance d'AngularJS gère magiquement les dépendances sans passage explicite, en utilisant un modèle d'injecteur pour fournir dynamiquement les dépendances à l'exécution.
  • Ember.js améliore les objets JavaScript avec des propriétés calculées, permettant aux propriétés de se comporter comme des fonctions, à la mise à jour automatiquement lorsque les dépendances changent.
  • La syntaxe JSX de React permet d'intégrer HTML dans JavaScript, qui est ensuite traitée par le transformateur JSX de React pour créer des composants d'interface utilisateur dynamiques.
  • L'article montre des solutions personnalisées pour l'injection de dépendance et les propriétés calculées, montrant comment les développeurs peuvent implémenter des fonctionnalités similaires dans leurs projets.
  • Comprendre les mécanismes sous-jacents des cadres JavaScript populaires peut permettre aux développeurs d'écrire du code plus efficace et maintenable.

Création d'éléments DOM à partir d'une chaîne

Avec la montée en puissance des applications à page unique, nous faisons beaucoup de choses avec JavaScript. Une grande partie de la logique de notre application a été déplacée vers le navigateur. C'est une tâche courante pour générer ou remplacer des éléments sur la page. Le code similaire à ce qui est montré ci-dessous est devenu très courant.

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le résultat est un nouvel élément ajouté au corps du document. Cette opération simple se fait avec une seule ligne de jQuery. Sans jQuery, le code est un peu plus complexe, mais pas beaucoup:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous avons défini notre propre méthode d'utilité StringTodom qui crée un élément temporaire. Nous avons changé sa propriété innerhtml et à la fin, nous avons simplement renvoyé le premier enfant qui, en pratique, est ce dont nous avions besoin. Cela a fonctionné de la même manière. Cependant, nous observerons différents résultats avec le code suivant:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Visuellement, sur la page, il n'y a pas de différences. Cependant, si nous vérifions le balisage généré avec les outils de développeur de Chrome, nous obtiendrons un résultat intéressant:

Révéler la magie du javascript

Il semble que notre fonction StringTodom ait créé juste un nœud de texte et non la balise

réelle. Mais en même temps, JQuery a réussi à le faire. Le problème est que la chaîne contenant l'élément HTML est exécutée via un analyseur dans le navigateur. Ce analyseur ignore les balises qui ne sont pas placées dans le bon contexte, et nous n'obtenons qu'un nœud texte. Une ligne de table sans table n'est pas valable pour le navigateur.

jQuery résout avec succès le problème en créant le bon contexte et extrait uniquement la pièce nécessaire. Si nous creusons un peu dans le code de la bibliothèque, nous verrons une carte comme celle-ci:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Chaque élément qui nécessite un traitement spécial a un tableau attribué. L'idée est de construire le bon élément DOM et de dépendre du niveau de nidification pour récupérer ce dont nous avons besoin. Par exemple, pour l'élément

, nous devons créer une table avec un enfant . Nous avons donc deux niveaux de nidification.

Ayant une carte, nous devons savoir quel type de balise nous voulons finalement. Le code suivant extrait le TR de

texte simple
<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le reste est de trouver le contexte approprié et de renvoyer l'élément DOM. Voici la variante finale de la fonction StringTodom:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Notez que nous vérifions s'il y a une balise dans la chaîne - correspond à! = NULL. Sinon, nous renvoyons simplement un nœud texte. Il y a encore une utilisation d'un

temporaire, mais cette fois, nous passons les bonnes balises afin que le navigateur puisse créer un arbre Dom valide. En fin de compte, en utilisant une boucle de temps, nous allons de plus en plus profondément jusqu'à ce que nous atteignions la balise recherchée.

Voici un codepen montrant notre implémentation:

Voir le stylo xlcgn par Krasimir tsonev (@krasimir) sur codepen.

Continuons en explorant la merveilleuse injection de dépendance AngularJS.

révélant l'injection de dépendance angulaire

Lorsque nous commençons à utiliser AngularJS, il impressionne avec sa liaison de données bidirectionnelle. La deuxième chose que nous remarquons est son injection de dépendance magique. Voici un exemple simple:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

C'est un contrôleur angularjs typique. Il effectue une demande HTTP, obtient les données d'un fichier JSON et la transmet à la portée actuelle. Nous n'exécutons pas la fonction Todoctrl - nous n'avons pas la possibilité de passer des arguments. Le cadre le fait. Alors, d'où viennent ces variables $ Scope et $ http? C'est une fonctionnalité super cool, qui ressemble fortement à la magie noire. Voyons comment cela se fait.

Nous avons une fonction JavaScript qui affiche les utilisateurs de notre système. La même fonction a besoin d'accéder à un élément DOM pour mettre le HTML généré et un wrapper Ajax pour obtenir les données. Afin de simplifier l'exemple, nous nous moquerons des données et de la demande HTTP.

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous utiliserons la balise

comme support de contenu. AjaxWrapper est l'objet simulant la demande et DataMockup est un tableau contenant nos utilisateurs. Voici la fonction que nous utiliserons:
<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Et bien sûr, si nous exécutons Displayusers (corps, ajaxwrapper), nous verrons les trois noms affichés sur la page et / API / utilisateurs demandés dans notre console. On pourrait dire que notre méthode a deux dépendances - Body et Ajaxwrapper. Donc, maintenant l'idée est de faire fonctionner la fonction sans passer d'arguments, c'est-à-dire que nous devons obtenir le même résultat en appelant simplement DisplayUsers (). Si nous faisons cela avec le code jusqu'à présent, le résultat sera:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

et c'est normal car le paramètre AJAX n'est pas défini.

La plupart des cadres qui fournissent des mécanismes d'injection de dépendance ont un module, généralement nommé injecteur . Pour utiliser une dépendance, nous devons l'enregistrer là-bas. Plus tard, à un moment donné, notre ressource est fournie à la logique de l'application par le même module.

Créons notre injecteur:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous n'avons besoin que de deux méthodes. Le premier, s'inscrit, accepte nos ressources (dépendances) et les stocke en interne. Le second accepte la cible de notre injection - la fonction qui a des dépendances et doit les recevoir comme paramètres. Le moment clé ici est que l'injecteur ne doit pas appeler notre fonction. C’est notre travail et nous devrions être en mesure de contrôler cela. Ce que nous pouvons faire dans la méthode Resolve est de renvoyer une fermeture qui enveloppe la cible et l'invoque. Par exemple:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

En utilisant cette approche, nous aurons la possibilité d'appeler la fonction avec les dépendances nécessaires. Et en même temps, nous ne modifions pas le flux de travail de l'application. L'injecteur est toujours quelque chose d'indépendant et ne tient pas de fonctionnalités liées à la logique.

Bien sûr, passer la fonction DisplayUsers à la méthode Resolve n'aide pas.

<span>var stringToDom = function(str) {
</span>  <span>var wrapMap = {
</span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>    <span>area: [1, '<map>', '</map>'],
</span>    <span>param: [1, '<object>', '</object>'],
</span>    <span>thead: [1, '<table>', '</table>'],
</span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>    <span>_default: [1, '<div>', '</div>']
</span>  <span>};
</span>  wrapMap<span>.optgroup = wrapMap.option;
</span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>  wrapMap<span>.th = wrapMap.td;
</span>  <span>var element = document.createElement('div');
</span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
</span>
  <span>if(match != null) {
</span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
</span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
</span>    str <span>= map[1] + str + map[2];
</span>    element<span>.innerHTML = str;
</span>    <span>// Descend through wrappers to the right content
</span>    <span>var j = map[0]+1;
</span>    <span>while(j--) {
</span>      element <span>= element.lastChild;
</span>    <span>}
</span>  <span>} else {
</span>    <span>// if only text is passed
</span>    element<span>.innerHTML = str;
</span>    element <span>= element.lastChild;
</span>  <span>}
</span>  <span>return element;
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous obtenons toujours la même erreur. L'étape suivante consiste à découvrir ce dont la cible passée a besoin. Quelles sont ses dépendances? Et voici la partie délicate que nous pouvons adopter à partir d'AngularJS. J'ai encore une fois creusé un peu dans le code du cadre et j'ai trouvé ceci:

<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
</span>  $http<span>.get('users/users.json').success(function(data) {
</span>    $scope<span>.users = data;
</span>  <span>});
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous avons délibérément sauté certaines pièces, car elles ressemblent plus aux détails de l'implémentation. C’est le code qui est intéressant pour nous. La fonction annotée est quelque chose comme notre méthode de résolution. Il convertit la fonction cible passée en une chaîne, supprime les commentaires (le cas échéant) et extrait les arguments. Utilisons cela et voyons les résultats:

<span>var dataMockup = ['John', 'Steve', 'David'];
</span><span>var body = document.querySelector('body');
</span><span>var ajaxWrapper = {
</span>  <span>get: function(path<span>, cb</span>) {
</span>    <span>console.log(path + ' requested');
</span>    <span>cb(dataMockup);
</span>  <span>}
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion

Voici la sortie de la console:

Révéler la magie du javascript

Si nous obtenons le deuxième élément du tableau Argdecl, nous trouverons les noms des dépendances nécessaires. C’est exactement ce dont nous avons besoin, car avoir les noms, nous pourrons fournir les ressources du stockage de l’injecteur. Voici la version qui fonctionne et couvre avec succès nos objectifs:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Notez que nous utilisons .split (/ ,? / g) pour convertir la chaîne domel, ajax en un tableau. Après cela, nous vérifions si les dépendances sont enregistrées et si oui, nous les transmettons à la fonction cible. Le code à l'extérieur de l'injecteur ressemble à ça:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

L'avantage d'une telle implémentation est que nous pouvons injecter l'élément DOM et le wrapper Ajax dans de nombreuses fonctions. Nous pourrions même distribuer la configuration de notre application comme celle-là. Il n'est pas nécessaire de passer des objets de classe à l'autre. Ce sont juste les méthodes de registre et de résolution.

Bien sûr, notre injecteur n'est pas parfait. Il y a encore une place pour les améliorations, comme par exemple le support de la définition de la portée. La fonction cible en ce moment est invoquée avec une portée nouvellement créée, mais normalement nous voulons passer le nôtre. Nous devons prendre en charge également l'envoi d'arguments personnalisés avec les dépendances.

L'injecteur devient encore plus compliqué si nous voulons que notre code fonctionne après minification. Comme nous le savons, les minifiants remplacent les noms des fonctions, les variables et même les arguments des méthodes. Et parce que notre logique repose sur ces noms, nous devons penser à la solution de contournement. Une solution possible provient à nouveau d'AngularJS:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Au lieu des seuls à afficher, nous passons les noms des dépendances réelles.

Notre exemple en action:

Voir le stylo bxdar par Krasimir tsonev (@krasimir) sur codepen.

Adopter les propriétés calculées d'Ember

Ember est l'un des cadres les plus populaires de nos jours. Il a des tonnes de fonctionnalités utiles. Il y en a un qui est particulièrement intéressant - les propriétés calculées. En résumé, les propriétés calculées sont des fonctions qui agissent comme des propriétés. Voyons un exemple simple tiré de la documentation de l'Ember:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Il y a une classe qui a des propriétés FirstName et LastName. La propriété calculée FullName renvoie la chaîne concaténée contenant le nom complet de la personne. Ce qui est étrange, c'est la partie où nous utilisons la méthode .property contre la fonction appliquée à FullName. Personnellement, je n’ai vu cela ailleurs. Et, encore une fois, un look rapide du code du cadre révèle la magie:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La bibliothèque modifie le prototype de l'objet de fonction global en ajoutant une nouvelle propriété. C'est une belle approche pour exécuter une logique pendant la définition d'une classe.

Ember utilise des Getters et des Setters pour fonctionner avec les données de l'objet. Cela simplifie l'implémentation des propriétés calculées car nous avons une couche de plus avant d'atteindre les variables réelles. Cependant, il sera encore plus intéressant si nous pouvons utiliser des propriétés calculées avec les objets JavaScript simples. Comme par exemple:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le nom est utilisé comme une propriété régulière mais en pratique est une fonction qui obtient ou définit FirstName et LastName.

Il existe une fonction de réapprovisionnement de JavaScript qui pourrait nous aider à réaliser l'idée. Jetez un œil à l'extrait suivant:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La méthode object.defineproperty pourrait accepter une portée, un nom d'une propriété, un getter et un secteur. Tout ce que nous avons à faire est d'écrire le corps des deux méthodes. Et c'est tout. Nous pourrons exécuter le code ci-dessus et nous obtiendrons les résultats attendus:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

objet.DefineProperty est exactement ce dont nous avons besoin, mais nous ne voulons pas forcer le développeur à l'écrire à chaque fois. Nous devrons peut-être fournir un polyfill, exécuter une logique supplémentaire ou quelque chose comme ça. Dans le cas idéal, nous voulons fournir une interface similaire à celle d'Ember. Une seule fonction fait partie de la définition de classe. Dans cette section, nous rédigerons une fonction utilitaire appelée Computize qui traitera notre objet et convertira en quelque sorte la fonction de nom en une propriété avec le même nom.

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous voulons utiliser la méthode du nom comme setter, et en même temps qu'un getteur. Ceci est similaire aux propriétés calculées d'Ember.

Ajoutons maintenant notre propre logique dans le prototype de l'objet de fonction:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Une fois que nous ajouterons les lignes ci-dessus, nous serons en mesure d'ajouter .Compué () à la fin de chaque définition de la fonction:

<span>var stringToDom = function(str) {
</span>  <span>var wrapMap = {
</span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>    <span>area: [1, '<map>', '</map>'],
</span>    <span>param: [1, '<object>', '</object>'],
</span>    <span>thead: [1, '<table>', '</table>'],
</span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>    <span>_default: [1, '<div>', '</div>']
</span>  <span>};
</span>  wrapMap<span>.optgroup = wrapMap.option;
</span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>  wrapMap<span>.th = wrapMap.td;
</span>  <span>var element = document.createElement('div');
</span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
</span>
  <span>if(match != null) {
</span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
</span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
</span>    str <span>= map[1] + str + map[2];
</span>    element<span>.innerHTML = str;
</span>    <span>// Descend through wrappers to the right content
</span>    <span>var j = map[0]+1;
</span>    <span>while(j--) {
</span>      element <span>= element.lastChild;
</span>    <span>}
</span>  <span>} else {
</span>    <span>// if only text is passed
</span>    element<span>.innerHTML = str;
</span>    element <span>= element.lastChild;
</span>  <span>}
</span>  <span>return element;
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

En conséquence, la propriété du nom ne contient plus de fonction, mais un objet qui a calculé une propriété égale à la propriété True et Func remplie de l'ancienne fonction. La vraie magie se produit dans la mise en œuvre de l'assistant Computize. Il passe par toutes les propriétés de l'objet et utilise l'objet.defineproperty où nous avons calculé les propriétés:

<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
</span>  $http<span>.get('users/users.json').success(function(data) {
</span>    $scope<span>.users = data;
</span>  <span>});
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Notez que nous supprimons le nom de la propriété d'origine. Dans certains objets de navigateur. DefineProperty ne fonctionne que sur les propriétés qui ne sont pas encore définies.

Voici la version finale de l'objet utilisateur qui utilise .Compué () Fonction.

<span>var dataMockup = ['John', 'Steve', 'David'];
</span><span>var body = document.querySelector('body');
</span><span>var ajaxWrapper = {
</span>  <span>get: function(path<span>, cb</span>) {
</span>    <span>console.log(path + ' requested');
</span>    <span>cb(dataMockup);
</span>  <span>}
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion

Une fonction qui renvoie le nom complet est utilisée pour changer FirstName et LastName. C'est l'idée derrière la vérification des arguments passés et le traitement du premier. S'il existe, nous l'avons divisé et appliquons les valeurs aux propriétés normales.

Nous avons déjà mentionné l'utilisation souhaitée, mais voyons-la une fois de plus:

<span>var displayUsers = function(domEl<span>, ajax</span>) {
</span>  ajax<span>.get('/api/users', function(users) {
</span>    <span>var html = '';
</span>    <span>for(var i=0; i < users.length; i++) {
</span>      html <span>+= '<p>' + users[i] + '</p>';
</span>    <span>}
</span>    domEl<span>.innerHTML = html;
</span>  <span>});
</span><span>}</span>
Copier après la connexion

Le codePen suivant montre notre travail dans la pratique:

Voir le stylo ahpqo par Krasimir tsonev (@krasimir) sur codepen.

Les modèles de réactions folles

Vous avez probablement entendu parler de la réaction du cadre de Facebook. Il est construit autour de l'idée que tout est un composant. Ce qui est intéressant, c'est la définition du composant. Jetons un coup d'œil à l'exemple suivant:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La première chose à laquelle nous commençons à penser est que c'est un javascript, mais celle invalide. Il y a une fonction de rendu, et il lancera probablement une erreur. Cependant, l'astuce est que ce code est placé dans une balise avec l'attribut de type personnalisé. Le navigateur ne le traite pas, ce qui signifie que nous sommes à l'abri des erreurs. React a son propre analyseur qui traduit le code écrit par nous en un JavaScript valide. Les développeurs de Facebook ont ​​appelé le langage XML comme le langage jsx . Leur transformateur JSX est de 390k et contient environ 12000 lignes de code. Donc, c'est un peu complexe. Dans cette section, nous créerons quelque chose de bien simple, mais toujours assez puissant. Une classe JavaScript qui analyse les modèles HTML dans le style de réact.

L'approche que Facebook a adoptée est de mélanger le code JavaScript avec le balisage HTML. Alors, disons que nous avons le modèle suivant:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

et un composant qui l'utilise:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

L'idée est que nous soulignons l'ID du modèle et définissons les données qui doivent être appliquées. Le dernier élément de notre implémentation est le moteur réel qui fusionne les deux éléments. Appelons cela le moteur et commençons-le comme ça:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous obtenons le contenu de la balise

Maintenant, écrivons notre fonction d'analyse. Notre première tâche consiste à distinguer le HTML des expressions. Par expressions, nous entendons des chaînes entre . Nous utiliserons un regex pour les trouver et une boucle simple pour parcourir toutes les correspondances:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le résultat du code ci-dessus est le suivant:

<span>var stringToDom = function(str) {
</span>  <span>var wrapMap = {
</span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>    <span>area: [1, '<map>', '</map>'],
</span>    <span>param: [1, '<object>', '</object>'],
</span>    <span>thead: [1, '<table>', '</table>'],
</span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>    <span>_default: [1, '<div>', '</div>']
</span>  <span>};
</span>  wrapMap<span>.optgroup = wrapMap.option;
</span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>  wrapMap<span>.th = wrapMap.td;
</span>  <span>var element = document.createElement('div');
</span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
</span>
  <span>if(match != null) {
</span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
</span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
</span>    str <span>= map[1] + str + map[2];
</span>    element<span>.innerHTML = str;
</span>    <span>// Descend through wrappers to the right content
</span>    <span>var j = map[0]+1;
</span>    <span>while(j--) {
</span>      element <span>= element.lastChild;
</span>    <span>}
</span>  <span>} else {
</span>    <span>// if only text is passed
</span>    element<span>.innerHTML = str;
</span>    element <span>= element.lastChild;
</span>  <span>}
</span>  <span>return element;
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Il n'y a qu'une seule expression et son contenu est un titre. La première approche intuitive que nous pouvons adopter consiste à utiliser la fonction de remplacement de JavaScript et à remplacer par les données de l'objet PASST COMP. Cependant, cela ne fonctionnera qu'avec les propriétés simples. Et si nous avons des objets imbriqués ou même si nous voulons utiliser une fonction. Comme par exemple:

<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
</span>  $http<span>.get('users/users.json').success(function(data) {
</span>    $scope<span>.users = data;
</span>  <span>});
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Au lieu de créer un analyseur complexe et d'inventer presque une nouvelle langue, nous pouvons utiliser Pure JavaScript. La seule chose que nous devons faire est d'utiliser la nouvelle syntaxe de fonction.

<span>var dataMockup = ['John', 'Steve', 'David'];
</span><span>var body = document.querySelector('body');
</span><span>var ajaxWrapper = {
</span>  <span>get: function(path<span>, cb</span>) {
</span>    <span>console.log(path + ' requested');
</span>    <span>cb(dataMockup);
</span>  <span>}
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous sommes en mesure de construire le corps d'une fonction exécutée plus tard. Donc, nous connaissons la position de nos expressions et ce qui se dresse exactement derrière eux. Si nous utilisons un tableau temporaire et un curseur, notre cycle ressemblera à ça:

<span>var text = $('<div>Simple text</div>');
</span>
<span>$('body').append(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

La sortie de la console montre que nous sommes sur la bonne voie:

<span>var stringToDom = function(str) {
</span>  <span>var temp = document.createElement('div');
</span>
  temp<span>.innerHTML = str;
</span>  <span>return temp.childNodes[0];
</span><span>}
</span><span>var text = stringToDom('<div>Simple text</div>');
</span>
<span>document.querySelector('body').appendChild(text);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Le tableau de code doit être transformé en une chaîne qui sera un corps d'une fonction. Par exemple:

<span>var tableRow = $('<tr><td>Simple text</td></tr>');
</span><span>$('body').append(tableRow);
</span>
<span>var tableRow = stringToDom('<tr><td>Simple text</td></tr>');
</span><span>document.querySelector('body').appendChild(tableRow);</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Il est assez facile d'atteindre ce résultat. Nous pouvons écrire une boucle qui passe par tous les éléments du tableau de code et vérifie si l'élément est une chaîne ou un objet. Cependant, cela ne couvre à nouveau qu'une partie des cas. Et si nous avons le modèle suivant:

<span>var wrapMap = {
</span>  <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>  <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>  <span>area: [1, '<map>', '</map>'],
</span>  <span>param: [1, '<object>', '</object>'],
</span>  <span>thead: [1, '<table>', '</table>'],
</span>  <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>  <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>  <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>  <span>_default: [1, '<div>', '</div>']
</span><span>};
</span>wrapMap<span>.optgroup = wrapMap.option;
</span>wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>wrapMap<span>.th = wrapMap.td;</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous ne pouvons pas simplement concaténer les expressions et nous attendre à faire répertorier les couleurs. Ainsi, au lieu d'ajouter une chaîne à une chaîne, nous les collecterons dans un tableau. Voici la version mise à jour de la fonction d'analyse:

<span>var match = <span>/&lt;<span>\s*\w.*?&gt;</span>/g</span>.exec(str);
</span><span>var tag = match[0].replace(<span>/&lt;/g</span>, '').replace(<span>/&gt;/g</span>, '');</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Une fois le tableau de code rempli, nous commençons à construire le corps de la fonction. Chaque ligne du modèle sera stockée dans un tableau r. Si la ligne est une chaîne, nous la nettoyons un peu en échappant aux citations et en supprimant les nouvelles lignes et onglets. Il est ajouté au tableau via la méthode push. Si nous avons un extrait de code, nous vérifions s'il ne s'agit pas d'un opérateur JavaScript valide. Si oui, alors nous ne l'ajoutons pas au tableau, mais nous le supprimons simplement en tant que nouvelle ligne. La console.log à la fin des sorties:

<span>var stringToDom = function(str) {
</span>  <span>var wrapMap = {
</span>    <span>option: [1, '<select multiple="multiple">', '</select>'],
</span>    <span>legend: [1, '<fieldset>', '</fieldset>'],
</span>    <span>area: [1, '<map>', '</map>'],
</span>    <span>param: [1, '<object>', '</object>'],
</span>    <span>thead: [1, '<table>', '</table>'],
</span>    <span>tr: [2, '<table><tbody>', '</tbody></table>'],
</span>    <span>col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
</span>    <span>td: [3, '<table><tbody><tr>', '</tr></tbody></table>'],
</span>    <span>_default: [1, '<div>', '</div>']
</span>  <span>};
</span>  wrapMap<span>.optgroup = wrapMap.option;
</span>  wrapMap<span>.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
</span>  wrapMap<span>.th = wrapMap.td;
</span>  <span>var element = document.createElement('div');
</span>  <span>var match = <span>/<<span>\s*\w.*?></span>/g</span>.exec(str);
</span>
  <span>if(match != null) {
</span>    <span>var tag = match[0].replace(<span>/</g</span>, '').replace(<span>/>/g</span>, '');
</span>    <span>var map = wrapMap[tag] || wrapMap._default, element;
</span>    str <span>= map[1] + str + map[2];
</span>    element<span>.innerHTML = str;
</span>    <span>// Descend through wrappers to the right content
</span>    <span>var j = map[0]+1;
</span>    <span>while(j--) {
</span>      element <span>= element.lastChild;
</span>    <span>}
</span>  <span>} else {
</span>    <span>// if only text is passed
</span>    element<span>.innerHTML = str;
</span>    element <span>= element.lastChild;
</span>  <span>}
</span>  <span>return element;
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

sympa, n'est-ce pas? JavaScript de travail correctement formaté, qui exécuté dans le contexte de notre composant produira le balisage HTML souhaité.

La dernière chose qui reste est le fonctionnement réel de notre fonction pratiquement créée:

<span>function <span>TodoCtrl</span>($scope<span>, $http</span>) {
</span>  $http<span>.get('users/users.json').success(function(data) {
</span>    $scope<span>.users = data;
</span>  <span>});
</span><span>}</span>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Copier après la connexion

Nous avons enveloppé notre code dans une instruction avec afin de l'exécuter dans le contexte du composant. Sans cela, nous avons besoin d'utiliser ce.title et ce.colors au lieu du titre et des couleurs.

Voici un codepen présentant le résultat final:

Voir le stylo gahej par Krasimir tsonev (@krasimir) sur codepen.

Résumé

Derrière les grands frameworks et bibliothèques sont des développeurs intelligents. Ils ont trouvé et utilisé des solutions délicates qui ne sont pas triviales, et même un peu magiques. Dans cet article, nous avons révélé une partie de cette magie. C'est bien que dans le monde JavaScript, nous puissions apprendre des meilleurs et utiliser leur code.

Le code de cet article est disponible en téléchargement depuis GitHub

Questions fréquemment posées (FAQ) sur la magie de JavaScript

Quelles sont les méthodes magiques en JavaScript et comment fonctionnent-elles?

Les méthodes magiques en JavaScript sont des méthodes spéciales qui fournissent des crochets dans le comportement d'une classe. Ils ne sont pas appelés directement mais sont invoqués lorsque certaines actions sont effectuées. Par exemple, la méthode toString () est une méthode magique qui est automatiquement appelée lorsqu'un objet doit être représenté comme une valeur de texte. Un autre exemple est la méthode de valeur de (), qui est appelée lorsqu'un objet doit être représenté comme une valeur primitive.

Comment puis-je utiliser des méthodes magiques dans JavaScript?

Les méthodes magiques en JavaScript peuvent être utilisées en les définissant dans votre objet ou classe. Par exemple, vous pouvez définir une méthode toString () dans votre objet pour personnaliser la façon dont votre objet sera représenté comme une chaîne. Voici un exemple simple:

Laissez Person = {
FirstName: "John",
LastName: "Doe",
toString: function () {
return this.firstname " "this.lastName;
}
};
console.log (personne.tostring ()); // "John Doe"

Quelle est la signification des fonctions magiques dans JavaScript?

Les fonctions magiques en JavaScript sont importantes car elles vous permettent de contrôler et de personnaliser la façon dont vos objets se comportent dans certaines situations. Ils peuvent rendre votre code plus intuitif et plus facile à comprendre, et fournir un moyen d'encapsuler et de protéger vos données.

Pouvez-vous fournir quelques exemples de fonctions magiques en javascript?

Bien sûr, bien sûr, Voici quelques exemples de fonctions magiques en javascript:

    1. toString (): Cette méthode renvoie une chaîne représentant l'objet.

    1. Valeurof (): Cette méthode renvoie la valeur primitive de l'objet.

    1. HasownProperty (): Cette méthode renvoie un booléen indiquant si l'objet a la propriété spécifiée.

Y a-t-il des limitations ou des inconvénients à l'utilisation de méthodes magiques dans JavaScript?

tandis que Les méthodes magiques peuvent être très utiles, elles ont également certaines limites. D'une part, ils peuvent rendre votre code plus complexe et plus difficile à déboguer, surtout si vous ne savez pas comment ils fonctionnent. Ils peuvent également conduire à un comportement inattendu s'ils ne sont pas utilisés correctement.

Comment JavaScript gère-t-il les méthodes magiques par rapport à d'autres langages de programmation?

Contrairement à certains autres langages de programmation, JavaScript n'a pas de concept formel de «Méthodes magiques». Cependant, il a certaines méthodes qui se comportent de la même manière, telles que ToString () et ValueOf (). Ces méthodes sont automatiquement appelées dans certaines situations, tout comme les méthodes magiques dans d'autres langues.

Quelles sont les meilleures pratiques pour utiliser des méthodes magiques en javascrip Incluez la compréhension quand et pourquoi les utiliser, les utiliser avec parcimonie pour éviter la complexité, et toujours tester votre code en détail pour s'assurer qu'il se comporte comme prévu.

Les méthodes magiques peuvent être utilisées avec JavaScript Des cadres comme React ou Vue?

Oui, les méthodes magiques peuvent être utilisées avec des frameworks JavaScript comme React ou Vue. Cependant, la façon dont ils sont utilisés peuvent varier en fonction du cadre. Il est toujours préférable de se référer à la documentation spécifique du framework pour les conseils.

Comment puis-je en savoir plus sur les méthodes magiques en JavaScript?

Il existe de nombreuses ressources disponibles pour en savoir plus sur les méthodes magiques en JavaScript. Vous pouvez commencer par la documentation officielle JavaScript, ainsi que des tutoriels et des cours en ligne. Vous pouvez également vous entraîner à utiliser dans vos propres projets pour acquérir une expérience pratique.

Y a-t-il des outils ou des bibliothèques qui peuvent aider à utiliser des méthodes magiques en javascript?

Il existe de nombreuses bibliothèques et Outils qui peuvent aider à utiliser les méthodes magiques en JavaScript. Par exemple, Lodash est une bibliothèque utilitaire JavaScript populaire qui fournit des méthodes utiles pour travailler avec des tableaux, des objets et d'autres types de données.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal