Maison > interface Web > js tutoriel > Tutoriel avancé JavaScript 5.6 Types d'empaquetage de base (détails)_Compétences Javascript

Tutoriel avancé JavaScript 5.6 Types d'empaquetage de base (détails)_Compétences Javascript

WBOY
Libérer: 2016-05-16 15:30:41
original
1232 Les gens l'ont consulté

Afin de faciliter le fonctionnement des valeurs de type de base, ECMAScript fournit également 3 types de référence spéciaux : Boolean, Number, String.

En fait, chaque fois qu'une valeur de type de base est lue, l'arrière-plan doit créer un objet du type wrapper de base correspondant, afin que nous puissions appeler certaines méthodes pour exploiter ces données.

var s1="some text";
  var s2=s1.substring(2);
  console.log(s2);//me text
Copier après la connexion

Dans cet exemple, s1 contient une chaîne, qui est une valeur de type de base. La deuxième ligne appelle la méthode subsstring() de s1 et enregistre le résultat renvoyé dans s2.

Lorsque la deuxième ligne de code accède à s1, le processus d'accès est en mode lecture, c'est-à-dire que la valeur de cette chaîne est lue dans la mémoire. Lors de l'accès à la chaîne en mode lecture, l'arrière-plan terminera automatiquement le traitement suivant. .

(1) Créer une instance de type String ;

(2) Appeler la méthode spécifiée sur l'instance ;

(3) Détruisez cette instance.

Les trois étapes ci-dessus peuvent être imaginées comme l'exécution du code suivant :

var s1=new String("some text");
  var s2=s1.substring(2);
  s1=null;
  console.log(s2);//me text
Copier après la connexion
Après ce traitement, la valeur de chaîne de base devient la même qu'un objet. Et les trois étapes ci-dessus sont également applicables aux valeurs booléennes et numériques correspondant respectivement aux types Booléen et Numérique

.

La principale différence entre les types de référence et les types d'emballage de base est la durée de vie de l'objet.

Les instances de types de référence créées à l'aide de l'opérateur new sont stockées ensemble en mémoire avant que le flux d'exécution ne quitte la portée actuelle. Cependant, les objets des types wrapper de base créés automatiquement n'existent qu'au moment où une ligne de code est exécutée, puis détruits. immédiatement. Cela signifie que nous ne pouvons pas ajouter de propriétés et de méthodes aux types de base au moment de l'exécution.

var s1="some text";
  s1.color="red";
  console.log(s1.color);//undefined
Copier après la connexion
La cause du problème est que l'objet String créé dans la deuxième ligne a été détruit lors de l'exécution de la troisième ligne de code. La troisième ligne de code crée son propre objet String, et cet objet n'a pas d'attribut de couleur. .

L'appel de typeof sur une instance d'un type wrapper de base renverra "object", et tous les objets du type wrapper de base seront convertis en la valeur booléenne true.

Le constructeur Object renverra également, comme une méthode d'usine, une instance du type d'emballage de base correspondant en fonction du type de valeur transmise.

var obj=new Object("some text");
  console.log(obj instanceof String);//true
Copier après la connexion
Si vous passez une chaîne au constructeur Object, une instance de String sera créée, si vous passez un paramètre numérique, vous obtiendrez une instance de Number, et si vous passez un paramètre booléen, vous obtiendrez un instance de booléen.

Il convient de noter qu'utiliser new pour appeler le constructeur du type d'emballage de base est différent de l'appel direct de la fonction de transformation du même nom.

var value="25";
  var number=Number(value);//转型函数
  console.log(typeof number);//number
  var obj=new Number(value);//构造函数
  console.log(typeof obj);//object
Copier après la connexion

Dans cet exemple, la variable number stocke la valeur de type de base 25 et la variable obj stocke une instance de Number.

5.6.1 Type booléen

Le type booléen est un type référence correspondant à une valeur booléenne. Pour créer un objet booléen, vous pouvez appeler le constructeur booléen comme suit et transmettre la valeur vraie ou fausse.

var booleanObject=new Boolean(true);
Copier après la connexion
Les instances du type booléen remplacent la méthode valueOf() pour renvoyer la valeur du type de base true ou false ; la méthode toString() est remplacée pour renvoyer les chaînes "true" et "false". Cependant, l'objet booléen dans ECMAScript. Ce n'est pas très utile car cela provoque souvent des malentendus.

L'un des problèmes les plus courants est l'utilisation d'objets booléens dans des expressions booléennes.

var falseObject=new Boolean(false);
  var result=falseObject&&true;
  console.log(result);//true
  var falseValue=false;
  result=falseValue&&true;
  console.log(result);//false
Copier après la connexion
Dans cet exemple, un objet booléen est créé en utilisant la valeur false. Ensuite, une expression logique AND est construite entre cet objet et la valeur de type de base true. Cette ligne de code dans l'exemple est exécutée sur falseObject plutôt que sur sa valeur (. false) Évaluation. Tous les objets de l'expression booléenne seront convertis en vrai, donc l'objet falseObject représente vrai dans l'expression booléenne.

Il existe deux différences entre les valeurs booléennes des types de base et des types de référence : premièrement, l'opération typeof renvoie "boolean" pour les types de base, tandis que "object" est renvoyé pour les types de référence. Deuxièmement, puisque les objets booléens sont des instances de. le type booléen, donc l'utilisation de l'opérateur instanceof pour tester un objet booléen renvoie vrai, tandis que tester une valeur booléenne d'un type de base renvoie faux.

console.log(typeof falseObject);//object
  console.log(typeof falseValue);//boolean
  console.log(falseObject instanceof Boolean);//true
  console.log(falseValue instanceof Boolean);//false
Copier après la connexion

5.6.2 Type de numéro

Number est un type référence correspondant à une valeur numérique. Pour créer un objet Number, vous pouvez transmettre la valeur correspondante au constructeur Number lors de son appel.

var numberObject=new Number(10);
  console.log(typeof numberObject);//object
Copier après la connexion
Comme le type Boolean, le type Number remplace également les méthodes valueOf(), toLocaleString() et toString().

La méthode réécrite valueOf() renvoie la valeur du type de base du cas de l'objet, et les deux autres méthodes renvoient la valeur sous forme de chaîne.

Vous pouvez transmettre un paramètre représentant la base à la méthode toString() et lui dire de renvoyer la forme chaîne de la valeur décimale.

var num=10;
  console.log(num.toString());//10
  console.log(num.toString(2));//1010
  console.log(num.toString(8));//12
  console.log(num.toString(10));//10
  console.log(num.toString(16));//a
Copier après la connexion
En plus des méthodes héritées, le type Number fournit également certaines méthodes pour formater des valeurs numériques en chaînes.

Parmi eux, la méthode toFixed() renverra la représentation sous forme de chaîne de la valeur en fonction des décimales spécifiées.

var num=10;

console.log(num.toFixed(2));//10.00


La valeur 2 est transmise ici à la méthode toFixed(), ce qui signifie combien de décimales sont affichées. Les décimales nécessaires sont remplies avec 0.

Si la valeur elle-même contient plus de décimales que spécifié, les valeurs proches de la décimale maximale spécifiée seront arrondies.

能够自动舍入的特性,使得toFixed()方法很适合处理货币值.但需要注意的是,不同浏览器给这个方法设定的舍入规则可能会有所不同.在给toFixed()传入0的情况下,IE8及之前的版本不能正确舍入范围在{(-0.94,-0.5],[0.5,0.94)}之间的值.对于这个范围内的值,IE会返回0,而不是-1或1;其他浏览器都能返回正确的值.IE9修复了这个问题.

另外可用于格式 化数值的方法是toExponential(),该方法返回以指数表示法(也称e表示法)表示数值的字符串形式.与toFixed()方法一样,toExponential()也接收一个参数,而且该参数同样也是指定输出结果中的小数位数.

var num=10;
  console.log(num.toExponential(1));//1.0e+1
Copier après la connexion

对于一个数值来说,toPrecision()方法可能会返回固定大小(fixed)格式,也可能返回指定(exponential)格式;具体规则是看哪种格式最合适.这个方法接收一个参数,即表示数值的所有数字的位数(不包括指数部分).

var num=99;
  console.log(num.toPrecision(1));//1e+2
  console.log(num.toPrecision(2));//99
  console.log(num.toPrecision(3));//99.0
Copier après la connexion

第二行是用一位数来表示99,第三行是用两位数来表示,第四行是用三位数来表示.

实际上,toPrecision()会根据要处理的数值决定到底是调用toFixed()还是调用toExponential(),而这三个方法都可以通过向上或向下舍入,做到以最准确的形式来表示带有正确小数位的值.

toPrecision()方法可以表现1到21位小数.

仍然不建议直接实例化Number类型.具体来讲,就是在使用typeof和instanceof操作符测试基本类型数值与引用类型数值时,得到的结果完全不同.

var numberObject=new Number(10);
  var numberValue=10;
  console.log(typeof numberObject);//object
  console.log(typeof numberValue);//number
  console.log(numberObject instanceof Number);//true
  console.log(numberValue instanceof Number);//false
Copier après la connexion

在使用typeof操作符测试基本类型数值时,始终会返回"number",而在测试Number对象时,则会返回"object”.类似地,Number对象是Number类型的实例,而基本类型的数值则不是.

5.6.3 String类型

String类型是字符串的对象包装类型,可以像下面这样使用String构造函数来创建.

var stringObject=new String("hello world");
Copier après la connexion

String对象的方法也可以在所有基本的字符串值中访问到.其中,继承的valueOf(),toLoaleString()和toString()方法,都返回对象所表示的基本字符串值.

String类型的每个实例都有一个length属性,表示字符串包含多个字符.

var stringValue="hello world";
  console.log(stringValue.length);
Copier après la connexion

应该注意的是,即使字符串中包含双字节字符(不是占一个字节的ASCII字符),每个字符也仍然算一个字符.

1.字符方法

两个用于访问字符串中特定字符的方法是:charAt()和charCodeAt().这两个方法都接收一个参数,即基于0的字符位置.

charAt()方法以单字符字符串的形式返回给定位置的那个字符.

如果想得到的不是字符而是字符编码,就需要使用charCodeAt()了.

ECMAScript还定义了另一个访问个别字符的方法.在支持此方法的浏览器中,可以使用方括号加数字索引来访问字符串中的特定字符.

var stringValue="hello world";
  console.log(stringValue[1]);//e
Copier après la connexion

使用方括号表示法访问个别字符的语法得到了IE8及FF,Safari,Chrome和Opera所有版本的支持.如果在IE7及更早版本中使用这种语法,会返回undefined值.

2.字符串操作方法

concat(),用于将一或多个字符串拼接起来,返回拼接得到的新字符串.

var stringValue="hello";
  var result=stringValue.concat("world");
  console.log(result);//helloworld
  console.log(stringValue);//hello
Copier après la connexion

concat()返回一个拼接的字符串,不改变原数组的值.它可以接受任意多个参数,也就是说可以通过它拼接任意多个字符串.

var stringValue="hello";
  var result=stringValue.concat("world","!")
  console.log(result);//hellowworld!
  console.log(stringValue);//hello
Copier après la connexion

虽然concat()是专门用来拼接字符串的方法,但实践中使用更多的还是加号操作符(+).而且,使用加号操作符在大多数情况下都比使用concat()方法要简便易行(特别是在拼接多个字符串的情况下).

ECMAScript还提供了三个基于子字符串创建新字符串的方法:slice(),substr()和substring().

这三个方法都会返回被操作字符串的一个子字符串,而且也都接受一或两个参数.第一个参数指定子字符串的开始位置,第二个参数(在指定的情况下)表示子字符串到哪里结束.slice()和substring()的第二个参数指定的是子字符串最后一个字符后面的位置.而substr()的第二个参数指定的则是返回的字符个数.如果没有给这些方法传递第二个参数,则将字符串的长度作为结束位置.与concat()方法一样,slice(),substr()和substring()也不会修改字符串本身的值--它们只是返回一个基本类型的字符串值,对原始字符串没有任何影响.

var stringValue="hello world";
  console.log(stringValue.slice(3));//lo world
  console.log(stringValue.substring(3));//lo world
  console.log(stringValue.substr(3));//lo world
  console.log(stringValue.slice(3,7));//lo w
  console.log(stringValue.substring(3,7));//lo w
  console.log(stringValue.substr(3,7));//lo worl
Copier après la connexion

substr()返回"lo worl”,因为它的第二个参数指定的是要返回的字符个数.

在传递给这些方法的参数是负值的情况下,slice()方法会将传入的负值与字符串的长度相加,substr()方法将负的第一个参数加上字符串的长度,而将负的第二个参数转换为0.最后,substring()方法会把所有负值参数都转换为0.

var stringValue="hello world";
  console.log(stringValue.slice(-3));//rld
  console.log(stringValue.substring(-3));//hello world
  console.log(stringValue.substr(-3));//rld
  console.log(stringValue.slice(3,-4));//lo w
  console.log(stringValue.substring(3,-4));//hel
  console.log(stringValue.substr(3,-4));//(空字符串)
Copier après la connexion

注意:IE的JavaScript实现在处理向substr()方法传递负值的情况时存在问题,它会返回原始的字符串.IE9修复了这个问题.

当第二个参数是负值时,三个方法的行为各不相同.slice()方法会把第二个参数转换成7,substring()方法会把第二个参数转换为0,而由于这个方法会将小的数作为开始位置,将较大的数作为结束位置.substr()也会将第二个参数转换成0,也就意味着返回包含零个字符的字符串,也就是一个空字符串.

3.字符串位置方法

有两个可以从字符串中查找子字符串的方法:indexOf()和lastIndexOf().这两个方法都是从一个字符串中搜索给定的子字符串,然后返子字符串的位置(如果没有找到该字符串,则返回-1).

indexOf()方法从字符串的开头向后搜索子字符串,而lastIndexOf()方法是从字符串的末尾向前搜索子字符串.

var stringValue="hello world";
  console.log(stringValue.indexOf("o"));//4
  console.log(stringValue.lastIndexOf("o"));//7
Copier après la connexion

如果"o”在这个字符串中仅出现一次,那么indexOf()和lastIndexOf()会返回相同的位置值.

这两个方法都可以接收可选的第二个参数,表示从字符串中的哪个位置开始搜索.换句话说,indexOf()会从该参数指定的位置向后搜索,忽略该位置之前的所有字符;而lastIndexOf()则会从指定的的位置向前搜索,忽略该位置之后的所有字符.

var stringValue="hello world";
  console.log(stringValue.indexOf("o"),6);//4 6
  console.log(stringValue.indexOf("o",6));//7
  console.log(stringValue.lastIndexOf("o",6));//4
var stringValue="Lorem ipsum dolor sit amet, consectetur adipisicing elit";
  var positions=new Array();
  var pos=stringValue.indexOf("e");
  while(pos>-1){
    positions.push(pos);
    pos=stringValue.indexOf("e",pos+1);
  }
  console.log(positions);//[3,24,32,35,52]
Copier après la connexion

这个例子通过不断增加indexOf()方法开始查找的位置,遍历了一个长字符串.在循环之外,首先找到了"e"在字符串中的初始位置,而进入循环后,则每次都给indexOf()传递上一次的位置加1.这样,就确保了每次搜索都从上一次找到的子字符串的后面开始.每次搜索返回的位置依次被保存在数组positions中,以便将来使用.

4.trim()方法

ECMAScript 5为所有字符串定义了trim()方法.这个方法会创建一个字符串的副本,删除前置及后缀的所有空格,然后返回结果.

var stringValue="  hello world  ";
  var trimmedStringValue=stringValue.trim();
  console.log(stringValue);//  hello world  
  console.log(trimmedStringValue);//hello world
Copier après la connexion

由于trim()返回的是字符串的副本,所以原始字符串中的前置及后缀空格会保持不变.支持这个方法的浏览器有IE9+,FF3.5+,Safari5+,Opera 10.5+和Chrome.此外,FF3.5+,Safari 5+和Chrome 8+还支持非标准的trimLeft()和trimRight()方法,分别用于删除字符串开头和末尾的空格.

5.字符串大小写转换方法

ECMAScript中涉及字符串大小写转换的方法有4个:toLowerCase(),toLocaleLowerCase(),toUpperCase()和toLocaleUpperCase().

var stringValue="hello world";
  console.log(stringValue.toLocaleUpperCase());//HELLO WORLD
  console.log(stringValue.toUpperCase());//HELLO WORLD
  console.log(stringValue.toLocaleLowerCase());//hello world
  console.log(stringValue.toLowerCase());//hello world
Copier après la connexion

一般来说,在不知道自己的代码将在哪种语言环境中运行的情况下,还是使用针对地区的方法更稳妥一些.

6.字符串的模式匹配方法

String类型定义了几个用于在字符串中匹配模式的方法.第一个方法就是match(),在字符串上调用这个方法,本质上与调用RegExp的exec()方法相同.match()方法只接受一个参数,要么是一个正则表达式,要么是一个RegExp对象.

var text="cat,bat,sat,fat";
  var pattern=/.at/;
  //与pattern.exec(text)相同
  var matches=text.match(pattern);
  console.log(matches.index);//0
  console.log(matches[0]);//cat
  console.log(pattern.lastIndex);//0
Copier après la connexion

本例中的match()方法返回了一个数组;如果是调用RegExp对象的exec()方法并传递本例中的字符串作为参数,那么也会得到与此相同的数组:数组的第一项是与整个模式匹配的字符串,之后的每一项(如果有)保存着与正则表达式中的捕获组匹配的字符串.

另一个用于查找模式的方法是search().这个方法的唯一参数与match()方法的参数相同:由字符串或RegExp对象指定的一个正则表达式.search()方法返回字符串中第一个匹配项的索引;如果没有找到匹配项,则返回-1.而且,search()方法始终是从字符串开头向后查找模式.

var text="cat,bat,sat,fat";
  var pos=text.search(/at/);
  console.log(pos);//1
Copier après la connexion

为了简化替换子字符串的操作,ECMAScript提供了replace()方法.这个方法接受两个参数:第一个参数可以是一个RegExp对象或者一个字符串(这个字符串不会被转换成正则表达式),第二个参数可以是一个字符串或者一个函数.如果第一个参数是字符串,那么只会替换第一个子字符串.要想替换所有子字符串,唯一的办法就是提供一个正则表达式,而且要指定全局(g)标志.

var text="cat,bat,sat,fat";
  var result=text.replace("at","ond");
  console.log(result);//cond,bat,sat,fat
  result=text.replace(/at/g,"ond");//cond,bond,sond,fond
Copier après la connexion

L'étape suivante consiste à remplacer tous les "at" par "ond" en changeant le premier paramètre par une expression régulière avec un indicateur global.

Si le deuxième paramètre est une chaîne, vous pouvez également utiliser des séquences de caractères spéciaux pour insérer la valeur obtenue par l'opération d'expression régulière dans la chaîne de résultat.

Ces séquences de caractères spéciaux fournies par ECMAScript sont répertoriées ci-dessous.

est utilisée. est utilisée.
Séquence de caractères Texte de remplacement
$$ $
$& Correspond à la sous-chaîne du modèle entier. Même valeur que RegExp.lastMatch
$' La sous-chaîne avant la sous-chaîne correspondante. La même valeur que RegExp.leftContext
$` La sous-chaîne après la sous-chaîne correspondante. La même valeur que RegExp.rightContext
$n Correspond à la sous-chaîne du nième groupe de capture, où n est égal à 0~9. Par exemple, $1 est la sous-chaîne qui correspond au premier groupe de capture et $2 est la sous-chaîne qui correspond au deuxième groupe de capture. on Si aucun groupe de capture n'est défini dans l'expression régulière, la chaîne vide
$nn Correspond à la sous-chaîne du nième groupe de capture, où nn est égal à 01~99. Par exemple, $01 est la sous-chaîne qui correspond au premier groupe de capture, $02 est la sous-chaîne qui correspond au deuxième groupe de capture, etc. . Si aucun groupe de capture n'est défini dans l'expression régulière, la chaîne vide

通过这些特殊的字符序列,可以使用最近一次匹配结果中的内容.

var text="cat,bat,sat,fat";
  result=text.replace(/(.at)/g,"word ($1)");
  console.log(result);//word(cat),word(bat),word(sat),word(fat)
Copier après la connexion

在此,每个以".at”结尾的单词都被替换了,替换结果是"word"后跟一对圆括号,而圆括号中是被字符序列$1所替换的单词.

replace()方法的第二个参数也可以是一个函数.在只有一个匹配项(即与模式匹配的字符串)的情况下,会向这个函数传递3个函数:模式的匹配项,模式匹配项在字符串的位置和原始字符串.在正则表达式中定义了多个捕获组的情况下,传递给函数的参数 依次是模式的匹配项,第一个捕获组的匹配项,第二个捕获组的匹配项....,但最后两个参数仍然分别是模式的匹配项在字符串中的位置和原始字符串.这个函数应该返回一个字符串,表示应该被替换的匹配项使用函数作为replace()方法的第二个参数可以实现更加精细的替换操作.

function htmlEscape(text){
    return text.replace(/[<>"&]/g,function(match,pos,originalText){
      switch(match){
        case "<":
          return "<";
        case ">":
          return ">";
        case "&":
          return "&";
        case "\"":
          return """;
      }
    });
  }
  console.log(htmlEscape("<p class=\"greeting\">Hello world!</p>*"));//<p class="greeting">Hello world!</p>*
Copier après la connexion

这里,我们为插入HTML代码定义了函数htmlEscape(),这个函数能够转义4个字符:小于号,大于号,和号以及双引号.实现这种转义的最简单方式,就是使用正则表达式查找这几个字符,然后定义一个能够针对每个匹配的字符返回特定HTML实例的函数.

最后一个与模式匹配有关的方法是split(),这个方法可以基于指定的分隔符将一个字符串分割成多个子字符串,并将结果放在一个数组中.分隔符可以是字符串,也可以是一个RegExp对象(这个方法不会将字符串看成正则表达式).split()方法可以接受可选的第二个参数,用于指定数组的大小,以便确保返回的数组不会超过既定大小.

var colorText="red,blue,green,yellow";
  var color1=colorText.split(",");
  console.log(color1);//["red", "blue", "green", "yellow"]
  var color2=colorText.split(",",2);
  console.log(color2);//["red", "blue"]
  var color3=colorText.split(/[^\,]+/);
  console.log(color3);//["", ",", ",", ",", ""]
Copier après la connexion

在最后一次调用split()返回的数组中,第一项和最后一项是两个空字符串.之所以会这样,是因为通过正则表达式指定的分隔符出现在了字符串的开头(即子字符串"red")和末尾(即子字符串"yellow").

对split()中正则表达式的支持因浏览器而异.尽管对于简单的模式没有什么差别,但对于未发现匹配项以及带有捕获组的模式,匹配的行为就不大相同了.以下是几种觉的差别.

IE8及之前的版本会忽略捕获组.IE9能正确地在结果中包含捕获组.

FF3.6及之前版本在捕获组未找到匹配项时,会在结果数组中包含空字符串;ECMA-262规定没有匹配项的捕获组在结果数组中应该用undefined表示.

在正则表达式中使用捕获组时还有其他微妙的差别.

7.localeCompare()方法

这个方法比较两个字符串,并返回下列值中的一个:

如果字符串在字母表中应该排在字符串参数之前,则返回一个负数(大多数情况下是-1,具体的值要视实现而定)

如果字符串等于字符串参数,则返回0.

如果字符串在字母表中应该排在字符串参数之后,则返回一个正数(大多数情况下是1,具体的值同样要视实现而定)

var stringValue="yellow";
  console.log(stringValue.localeCompare("brick"));//1
  console.log(stringValue.localeCompare("yellow"));//0
  console.log(stringValue.localeCompare("zoo"));//-1
Copier après la connexion

因为localeCompare()返回的数值取决于实现,所以最好是像下面例子所示的这样使用这个方法.

function determineOrder(value){
    var result=stringValue.localeCompare(value);
    if(result<0){
      console.log("The string 'yellow' comes before the string '"+value+"'.");
    }else if(result>0){
      console.log("The string 'yellow' comes after the string '"+value+ "'.");
    }else{
      console.log("The string 'yellow' is equal to the string '"+value+"'.");
    }
  }
  determineOrder("brick");
  determineOrder("yellow");
  determineOrder("zoo");
Copier après la connexion

8.fromCharCode()方法

另外,String构造函数还有一个静态方法:fromCharCode().这个方法的任务是接收一或多个字符编码,然后将它们转换成一个字符串.从本质上来看,这个方法与实例方法charCodeAt()执行的是相反的操作.

以上内容是小编给大家介绍的关于JavaScript高级教程5.6之基本包装类型(详细),希望大家喜欢。

source:php.cn
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal