Maison > interface Web > js tutoriel > Trois bizarreries JavaScript que les développeurs Java / C devraient connaître

Trois bizarreries JavaScript que les développeurs Java / C devraient connaître

Lisa Kudrow
Libérer: 2025-02-20 10:28:12
original
709 Les gens l'ont consulté

Three JavaScript Quirks That Java/C Developers Should Know

Points de base

  • Contrairement à C ou Java, la portée de JavaScript est basée sur la fonction, non basée sur des blocs; if for L'élévation de JavaScript signifie que les variables et les déclarations de fonction sont déplacées en haut de leur portée incluse pendant la compilation, mais l'initialisation n'est pas élevée.
  • Les fonctions en JavaScript sont traitées comme des citoyens de première classe, ce qui signifie qu'ils peuvent être stockés en variables, passés sous forme de paramètres, renvoyés par d'autres fonctions et ont des propriétés comme des objets.
  • L'instruction
  • (variable de portée dynamique) dans JavaScript a été obsolète car elle peut provoquer des erreurs d'exécution et confuse de nature.
  • with JavaScript prend en charge les fermetures, permettant aux fonctions d'accéder aux variables des fonctions externes après le retour, améliorant ainsi la confidentialité des données et permettant de puissants modes de programmation tels que les modules et les variables privées.
JavaScript peut être un langage trompeur, il peut être douloureux car il n'est pas cohérent à 100%. Il est connu qu'il a de mauvaises parties de
table.sp_table {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
}
table.sp_table td, table.sp_table th {
  border: solid 1px #ccc;
  padding: 10px;
  line-height: 1.5;
  text-align: center;
  width: 20%;
}
table.sp_table tr td:first-child {
  font-weight: bold;
}
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-à-dire des fonctions déroutantes ou redondantes qui devraient être évitées: les déclarations infâmes, les variables globales implicites et les exceptions de comportement de comparaison sont probablement les plus célèbres. JavaScript est l'un des générateurs de flammes les plus réussis de l'histoire! Outre les défauts qu'il a (partiellement résolus dans la nouvelle spécification ECMAScript), la plupart des programmeurs détestent JavaScript pour deux raisons: - DOM, ils pensent à tort que cela équivaut à la langue javascript, qui a une très mauvaise API. - Ils sont passés de langues comme C et Java à JavaScript. La syntaxe de JavaScript les a fait croire que cela fonctionnait de la même manière que ces langues impératives. Ce malentendu peut entraîner une confusion, une frustration et une erreur.

C'est pourquoi, généralement, JavaScript a une pire réputation qu'il ne le mérite. Au cours de ma carrière, j'ai remarqué certains modèles: la plupart des développeurs avec des arrière-plans Java ou C / C pensent que les mêmes fonctionnalités linguistiques en JavaScript, et elles sont complètement différentes. Cet article recueille les fonctionnalités linguistiques les plus gênantes, en comparant les approches Java aux approches JavaScript pour montrer les différences et mettre en évidence les meilleures pratiques en JavaScript. with

Scope

La plupart des développeurs commencent à utiliser JavaScript car ils sont obligés de le faire, et presque tous les développeurs commencent à écrire du code avant de passer du temps à apprendre la langue. Chacun de ces développeurs a été dupe par la portée JavaScript au moins une fois. Parce que la syntaxe de JavaScript est très similaire à celle de la série C (intentionnellement), séparant le corps des fonctions, si et pour avec des accolades, les gens s'attendraient raisonnablement à la portée lexicale Block-Level . Malheureusement, ce n'est pas le cas. Premièrement, dans JavaScript, la portée variable est déterminée par les fonctions, et non par les supports. En d'autres termes, si et pour les corps ne créent pas de nouvelles portée, et les variables déclarées dans leur corps sont en fait promues, c'est-à-dire créées au début de la fonction la plus intérieure qui la déclare, sinon la portée mondiale. Deuxièmement, l'existence des instructions with oblige la portée JavaScript à devenir dynamique et ne peut être déterminée qu'à l'exécution. Vous ne serez peut-être pas surpris d'apprendre que l'utilisation des instructions with a été obsolète: JavaScript sans with sera en fait un langage à portée lexical, c'est-à-dire que la portée peut être complètement déterminée en regardant le code. Formel, en javascript, il existe quatre façons de pénétrer dans la portée: - Définition du langage: par défaut, toutes les lunettes contiennent des noms this et arguments. - Paramètres formels: La portée de tout paramètre (formel) déclaré pour une fonction appartient au corps de la fonction. - Déclaration de fonction. - Déclaration variable.

Une autre complexité est causée par la portée globale implicite des affectations variables pour (implicitement) non déclaré dans le mot-clé var. Cette folie est combinée avec une affectation implicite de la portée globale à this références lors de l'appel d'une fonction sans liaison explicite (plus sur la section suivante). Avant de creuser les détails, clarifions les bons modèles pour éviter la confusion: utilisez motif strict ('use strict';) et déplacez toutes les variables et déclarations de fonction en haut de chaque fonction; à l'intérieur pour et si les blocs et la déclaration de fonctions dans ces blocs (cela dépasse le cadre de cet article pour différentes raisons).

élévation

L'élévation est une méthode simplifiée pour expliquer le comportement réel des instructions. La variable promue est déclarée au début de la fonction qu'il contient et est initialisée à undefined. L'affectation se déroule ensuite dans la ligne réelle de la déclaration d'origine. Veuillez consulter l'exemple suivant:

table.sp_table {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
}
table.sp_table td, table.sp_table th {
  border: solid 1px #ccc;
  padding: 10px;
  line-height: 1.5;
  text-align: center;
  width: 20%;
}
table.sp_table tr td:first-child {
  font-weight: bold;
}
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

Quelle est la valeur que vous vous attendez à imprimer à la console? Seriez-vous surpris par la sortie suivante?

table.sp_table {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
}
table.sp_table td, table.sp_table th {
  border: solid 1px #ccc;
  padding: 10px;
  line-height: 1.5;
  text-align: center;
  width: 20%;
}
table.sp_table tr td:first-child {
  font-weight: bold;
}
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

Dans le bloc if, l'instruction var ne déclare pas une copie locale de la variable i, mais écrase plutôt la variable précédemment déclarée. Notez que l'instruction First console.log imprime la valeur réelle de la variable i, qui est initialisée à undefined. Vous pouvez le tester en utilisant la directive "use strict"; comme première ligne de la fonction. En mode strict, les variables doivent être déclarées avant de les utiliser, mais vous pouvez vérifier que le moteur JavaScript ne signale pas d'erreurs en raison de la déclaration. Soit dit en passant, veuillez noter que vous ne signalerez pas d'erreur en raison de la redéclations var: Si vous souhaitez attraper de telles erreurs, vous feriez mieux d'utiliser un linter comme Jshint ou Jslint pour gérer votre code. Voyons maintenant un autre exemple pour mettre en évidence une autre utilisation sujet aux erreurs des déclarations variables:

function myFunction() {
  console.log(i);
  var i = 0;
  console.log(i);
  if (true) {
    var i = 5;
    console.log(i);
  }
  console.log(i);
}
Copier après la connexion
Copier après la connexion
Copier après la connexion

Bien que vous puissiez vous attendre à ce que le corps if soit exécuté car une copie locale de la variable nommée test() est déclarée à l'intérieur de la fonction notNull, et elle est promue par . Type Obligatoire fonctionne ici aussi.

Déclaration de fonction et expression de fonction

L'élévation ne s'applique pas seulement aux variables, mais

les expressions de fonction (ce sont en fait des variables) et Les déclarations de fonction seront également promues. Ce sujet doit être traité plus attentivement que je ne l'ai fait ici, mais en bref, les déclarations de fonction se comportent à peu près les mêmes que les expressions de fonction, sauf que leurs déclarations sont déplacées au début de leur portée. Considérez l'exemple suivant montrant le comportement de la déclaration de fonction:

<code>undefined
0
5
5</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion
Comparez maintenant cela avec l'exemple suivant montrant le comportement des expressions de fonction:

var notNull = 1;
function test() {
  if (!notNull) {
    console.log("Null-ish, so far", notNull);
    for(var notNull = 10; notNull < 20; notNull++) {
      //..
    }
    console.log("Now it's not null", notNull);
  }
  console.log(notNull);
}
Copier après la connexion
Copier après la connexion
Copier après la connexion
Veuillez vous référer à la section de référence pour une compréhension approfondie de ces concepts.

avec

L'exemple suivant montre une situation où la portée ne peut être déterminée qu'au moment de l'exécution:

function foo() {
    // 函数声明
    function bar() {
        return 3;
    }
    return bar();

    // 此函数声明将被提升并覆盖之前的声明
    function bar() {
        return 8;
    }
}
Copier après la connexion
Copier après la connexion
Si

a un champ nommé y, la fonction x retournera foo(), sinon 123 sera retourné. Cette pratique de codage peut être la source des erreurs d'exécution, il est donc fortement recommandé d'éviter l'instruction y.x. with

Dans l'attente: Ecmascript 6

La spécification

ecmascript 6 ajoutera une cinquième méthode pour ajouter une étendue au niveau du bloc: l'instruction

. Considérez le code suivant: let

function foo() {
    // 函数表达式
    var bar = function() {
        return 3;
    };
    return bar();

    // 变量 bar 已经存在,并且永远不会到达此代码
    var bar = function() {
        return 8;
    };
}
Copier après la connexion
Dans ECMAScript 6, en utilisant

à l'intérieur du corps de if déclare let pour créer une nouvelle variable locale dans le bloc i. En tant qu'alternative non standard, le bloc if peut être déclaré comme suit: let

function foo(y) {
  var x = 123;
  with(y) {
    return x;
  }
}
Copier après la connexion
Dans le code ci-dessus, les variables

et i n'existent que dans le bloc. Au moment de la rédaction du moment de la rédaction, la prise en charge de j est limitée, même pour Chrome. let

Résumé de la portée

Le tableau suivant résume la portée dans différentes langues:

特性 Java Python JavaScript 警告
作用域 词法(块) 词法(函数、类或模块) 它与 Java 或 C 的工作方式大相径庭
块作用域 let 关键字(ES6) 再一次警告:这不是 Java!
提升 不可能! 仅提升变量和函数表达式的声明。对于函数声明,也会提升定义
函数 作为内置类型 回调/命令模式对象(或 Java 8 的 lambda)
动态创建 evalFunction 对象 eval 存在安全问题,Function 对象可能无法按预期工作
属性 可以具有属性 无法限制对函数属性的访问
闭包 弱化,只读,在匿名内部类中 弱化,只读,在嵌套的 def 中 内存泄漏

Fonction

Une autre caractéristique très mal compris de JavaScript est que les fonctions, en particulier dans les langages de programmation impératifs tels que Java, il n'y a pas de concept de fonctions. En fait, JavaScript est un langage de programmation fonctionnelle. Eh bien, ce n'est pas un langage de programmation fonctionnel pur comme Haskell - il a toujours un style impératif après tout, et encourage la mutabilité plutôt que de simplement permettre, tout comme Scala. Cependant, JavaScript peut être utilisé comme un langage de programmation purement fonctionnel, avec des appels de fonction sans aucun effet secondaire.

Citizen de première classe

Les fonctions dans JavaScript peuvent être traitées comme n'importe quel autre type, tel que la chaîne et le nombre: elles peuvent être stockées en variables, passées sous forme de paramètres aux fonctions, renvoyées par fonctions et stockées dans un tableau. Les fonctions peuvent également avoir des propriétés et peuvent être modifiées dynamiquement, car ...

objet

Un fait très surprenant pour la plupart des débutants JavaScript est que les fonctions sont en fait des objets. Dans JavaScript, chaque fonction est en fait un objet de fonction. Le constructeur de fonction crée un nouvel objet de fonction:

table.sp_table {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
}
table.sp_table td, table.sp_table th {
  border: solid 1px #ccc;
  padding: 10px;
  line-height: 1.5;
  text-align: center;
  width: 20%;
}
table.sp_table tr td:first-child {
  font-weight: bold;
}
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

Ceci est presque équivalent à:

function myFunction() {
  console.log(i);
  var i = 0;
  console.log(i);
  if (true) {
    var i = 5;
    console.log(i);
  }
  console.log(i);
}
Copier après la connexion
Copier après la connexion
Copier après la connexion

Je dis qu'ils sont presque équivalents car l'utilisation du constructeur de fonction est moins efficace, produit des fonctions anonymes et ne crée pas de fermetures pour leur contexte de création. Les objets de fonction sont toujours créés dans la portée globale. La fonction (le type de fonction) est construite sur l'objet. Cela peut être facilement vu en vérifiant toute fonction que vous déclarez:

<code>undefined
0
5
5</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela signifie que la fonction peut et a des propriétés. Certains d'entre eux sont affectés aux fonctions au moment de la création, tels que des noms ou des longueurs. Ces propriétés renvoient respectivement le nom et le nombre de paramètres dans la définition de la fonction. Considérez l'exemple suivant:

var notNull = 1;
function test() {
  if (!notNull) {
    console.log("Null-ish, so far", notNull);
    for(var notNull = 10; notNull < 20; notNull++) {
      //..
    }
    console.log("Now it's not null", notNull);
  }
  console.log(notNull);
}
Copier après la connexion
Copier après la connexion
Copier après la connexion

mais vous pouvez même définir vous-même de nouvelles propriétés pour toute fonction:

function foo() {
    // 函数声明
    function bar() {
        return 3;
    }
    return bar();

    // 此函数声明将被提升并覆盖之前的声明
    function bar() {
        return 8;
    }
}
Copier après la connexion
Copier après la connexion

Résumé de la fonction

Le tableau suivant décrit les fonctions dans Java, Python et JavaScript:

特性 Java Python JavaScript 警告
函数作为内置类型 lambda,Java 8 回调/命令模式对象(或 Java 8 的 lambda)
动态创建 evalFunction 对象 eval 存在安全问题,Function 对象可能无法按预期工作
属性 可以具有属性 无法限制对函数属性的访问

Clôture

Si on me demandait de choisir ma fonctionnalité JavaScript préférée, je choisirais la fermeture sans hésitation. JavaScript est le premier langage de programmation grand public à introduire des fermetures. Comme vous le savez, Java et Python ont depuis longtemps affaibli les versions de fermetures à partir desquelles vous ne pouvez lire que (certaines) valeurs des lunettes fermées. Par exemple, dans Java, les classes intérieures anonymes offrent une fonctionnalité de type fermeture avec certaines limitations. Par exemple, les variables locales finales ne peuvent être utilisées que dans leur portée - plus précisément, leurs valeurs peuvent être lues. JavaScript permet un accès complet aux variables et fonctions de portée externes. Ils peuvent être lus, écrits et même cachés par des définitions locales si nécessaire: vous pouvez voir des exemples de tous ces cas dans la section Scope. Ce qui est plus intéressant, c'est que la fonction créée dans la fermeture se souvient de l'environnement dans lequel il a été créé. En combinant les fermetures et la nidification des fonctions, vous pouvez avoir des fonctions externes renvoie des fonctions internes sans les exécuter. De plus, vous pouvez faire des variables locales de fonctions externes dure longtemps dans la fermeture de leurs fonctions internes, même si l'exécution de la fonction qui les déclare a terminée. Il s'agit d'une fonctionnalité très puissante, mais elle présente également ses inconvénients, car il s'agit d'une cause courante de fuites de mémoire dans les applications JavaScript. Quelques exemples illustreront ces concepts:

table.sp_table {
  width: 100%;
  border-collapse: collapse;
  border-spacing: 0;
}
table.sp_table td, table.sp_table th {
  border: solid 1px #ccc;
  padding: 10px;
  line-height: 1.5;
  text-align: center;
  width: 20%;
}
table.sp_table tr td:first-child {
  font-weight: bold;
}
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 fonction ci-dessus makeCounter() crée et renvoie une autre fonction qui suit l'environnement qu'il a créé. Bien que l'exécution de counter soit terminée lorsque la variable makeCounter() est allouée, la variable locale i reste dans la fermeture de displayCounter et peut donc être accessible à l'intérieur de son corps. Si nous voulons exécuter makeCounter à nouveau, cela créera une nouvelle fermeture où l'entrée pour i est différente:

function myFunction() {
  console.log(i);
  var i = 0;
  console.log(i);
  if (true) {
    var i = 5;
    console.log(i);
  }
  console.log(i);
}
Copier après la connexion
Copier après la connexion
Copier après la connexion

Pour le rendre plus intéressant, nous pouvons mettre à jour la fonction makeCounter() pour accepter un paramètre:

<code>undefined
0
5
5</code>
Copier après la connexion
Copier après la connexion
Copier après la connexion

Les paramètres de fonction externe sont également enregistrés dans la fermeture, nous n'avons donc pas besoin de déclarer les variables locales cette fois. Chaque appel makeCounter() se souviendra de la valeur initiale que nous définissons et continuera de compter. Les fermetures sont essentielles pour de nombreux modèles JavaScript de base: espaces de noms, modules, variables privées, la mémoire ne sont que les plus célèbres. Par exemple, voyons comment simuler des variables privées pour un objet:

var notNull = 1;
function test() {
  if (!notNull) {
    console.log("Null-ish, so far", notNull);
    for(var notNull = 10; notNull < 20; notNull++) {
      //..
    }
    console.log("Now it's not null", notNull);
  }
  console.log(notNull);
}
Copier après la connexion
Copier après la connexion
Copier après la connexion

En utilisant ce modèle, en utilisant des fermetures, nous pouvons créer un wrapper pour le nom de la propriété et utiliser nos propres setters et getters. ES5 rend cela beaucoup plus facile car vous pouvez créer des objets pour leurs propriétés à l'aide de Getters et Setters et de contrôler l'accès aux propriétés elles-mêmes au meilleur grain.

Résumé de clôture

Le tableau suivant décrit les fermetures dans Java, Python et JavaScript:

特性 Java Python JavaScript 警告
闭包 弱化,只读,在匿名内部类中 弱化,只读,在嵌套的 def 中 内存泄漏
记忆化模式 必须使用共享对象 可以使用列表或字典 最好使用惰性求值
命名空间/模块模式 不需要 不需要
私有属性模式 不需要 不可能 可能令人困惑

Conclusion

Dans cet article, je présente trois fonctionnalités de JavaScript qui sont souvent mal comprises par les développeurs de différentes langues, en particulier Java et C. En particulier, nous discutons des concepts tels que la portée, la promotion, les fonctions et les fermetures. Si vous souhaitez creuser dans ces sujets, voici une liste de certains articles que vous pouvez lire: - Portée dans JavaScript - Déclarations de fonctions et expressions de fonction - let Instructions et let Blocks

FAQ sur les fonctionnalités JavaScript (FAQ)

Quelle est la différence entre "==" et "===" dans JavaScript?

Dans JavaScript, "==" et "===" sont des opérateurs de comparaison, mais ils fonctionnent différemment. L'opérateur «==» est appelé l'opérateur d'égalité en vrac. Il compare si les deux valeurs sont égales après avoir effectué une conversion de type nécessaire. Cela signifie que si vous comparez un nombre à une chaîne avec un littéral numérique, il renverra vrai. Par exemple, "5" == 5 reviendra True. D'un autre côté, "===" est un opérateur d'égalité strict. Il n'effectue pas de conversion de type, donc si les deux types de valeur sont différents, il renvoie faux. Par exemple, "5" === 5 reviendra faux car l'un est une chaîne et l'autre est un nombre.

Pourquoi JavaScript a-t-il à la fois nul et indéfini?

Dans JavaScript, Null et Undefined sont des valeurs spéciales qui n'existent pas. Cependant, ils sont utilisés légèrement différemment. Undefined signifie que la variable a été déclarée mais n'a pas encore été attribuée. Null, en revanche, est une valeur d'affectation, n'indiquant aucune valeur ou aucun objet. Cela implique que la valeur de la variable n'existe pas, tandis que non définie signifie que la variable elle-même n'existe pas.

Quelle est l'amélioration de JavaScript?

L'élévation est un mécanisme en JavaScript qui déplace les variables et les déclarations de fonction au sommet de sa portée incluse pendant la phase de compilation. Cela signifie que vous pouvez utiliser des variables et des fonctions avant de les déclarer. Cependant, il convient de noter que seules les déclarations seront promues et que l'initialisation ne sera pas promue. Si la variable est déclarée et initialisée après l'avoir utilisée, la valeur ne sera pas définie.

Quelle est la différence entre les variables globales et les variables locales en JavaScript?

En JavaScript, les variables peuvent être des variables globales ou locales. Les variables globales sont des variables déclarées en dehors de toute fonction, ou variables déclarées avec le mot clé "VAR". Il est accessible à partir de n'importe quelle fonction du script. Les variables locales, en revanche, sont des variables déclarées dans une fonction à l'aide du mot-clé "var". Il ne peut être accessible que dans les fonctions qu'il déclare.

Quel est le mot-clé "ce" dans JavaScript?

Le mot clé "ce" dans JavaScript est un mot-clé spécial, qui fait référence au contexte de l'appel d'une fonction. Sa valeur dépend de la façon dont la fonction est appelée. Dans une méthode, "ce" fait référence à l'objet propriétaire. Individuellement, "ce" fait référence à un objet global. Dans une fonction, «ce» fait référence à un objet global. Dans un événement, «ce» fait référence à l'élément qui reçoit l'événement.

Quelles sont les fermetures en JavaScript?

Une fermeture en JavaScript est une fonction qui peut accéder à sa propre portée, à la portée et à la portée globale des fonctions externes, ainsi que des paramètres et variables de fonction d'accès. Cela permet à la fonction d'accéder aux variables dans la fonction externe renvoyée, en gardant les variables en mémoire et permet aux usines de confidentialité et de fonction des données.

Quelle est la différence entre les déclarations de fonction et les expressions de fonction dans JavaScript?

Dans JavaScript, les fonctions peuvent être définies à bien des égards, dont deux sont des déclarations de fonction et des expressions de fonction. Une déclaration de fonction définit une fonction nommée et la déclaration est promue, permettant à la fonction d'être utilisée avant de la définir. Une expression de fonction définit une fonction dans une expression et n'est pas promue, ce qui signifie qu'elle ne peut pas être utilisée avant sa définition.

Quelle est la différence entre "let", "var" et "const" dans javascript?

"Let", "var" et "const" sont tous utilisés pour déclarer des variables en JavaScript, mais ils ont des règles de portée différentes. "var" est dans la fonction de fonction, ce qui signifie qu'il ne peut être utilisé que dans les fonctions qu'il déclare. "Soit" et "const" sont scoés en blocs, ce qui signifie qu'ils ne peuvent être utilisés que dans les blocs qu'ils déclarent. La différence entre "Let" et "const" est que "Let" vous permet de réaffecter des variables, contrairement à "const".

Quelle est la différence entre les objets et les tableaux en javascript?

En JavaScript, les objets et les tableaux sont utilisés pour stocker des données, mais ils sont stockés de différentes manières. Un objet est une collection de propriétés, où chaque propriété est une paire de valeurs clés. Une clé est une chaîne et une valeur peut être n'importe quel type de données. Un tableau est un type spécial d'objet qui représente une liste d'éléments. Les clés sont des index numériques et les valeurs peuvent être de n'importe quel type de données.

Quelle est la différence entre les méthodes et les fonctions en JavaScript?

Dans JavaScript, une fonction est un bloc de code conçu pour effectuer une tâche spécifique, et c'est une entité distincte qui peut être utilisée au besoin. D'un autre côté, une méthode est une fonction associée à un objet, ou en d'autres termes, une méthode est une propriété d'un objet en fonction. Les méthodes sont définies de la même manière que les fonctions ordinaires, sauf qu'elles doivent se voir attribuer des valeurs comme des attributs d'objets.

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