0

0

JavaScript 基础知识:第 3 部分

心靈之曲

心靈之曲

发布时间:2024-10-08 19:27:08

|

396人浏览过

|

来源于dev.to

转载

javascript 基础知识:第 3 部分

之前在 javascript essentials:第 2 部分中,我们讨论了很多有关字符串属性和方法,以及拆分为数组时索引字符串的内容。在这一部分,我们将看看:

  • 对象
  • 数组

目的

我们已经讨论了对象并看到了对象的一些示例。

示例


const profile = {
  name: "john doe",
  "date of birth": "2000-12-25",
  profession: "software engineer",
  "number of pets": 2,
  "weight of protein in grams": 12.5,
  "has a job": true,
};

console.log(profile);


我们可以使用点运算符访问对象的属性。我们可以将 profile.name 设置为 name 的值。我们还可以为任何属性或新属性分配或重新分配值。还有另一种方法可以访问属性的值。在索引中,我们传递一个数字,但在这种方法中,我们传递属性名称。个人资料[“属性”]。因此 profile.name 和 profile["name"] 将具有相同的结果。当属性名称中有空格时,我们使用后者。我可能没有提到这一点,但是,最好避免带有空格的属性名称。 (你还记得camelcasing、snake_casing、pascalcasing、constant_casing等)。

立即学习Java免费学习笔记(深入)”;


console.log(`name on profile: ${profile.name}`);
console.log(`profession: ${profile.profession}`);
console.log(`number of pets: ${profile["number of pets"]}`);
console.log(`protein weight (g): ${profile["weight of protein in grams"]}g`);
console.log(`is employed: ${profile["has a job"]}`);


我们还可以更改对象中的数据。


profile.name = "michael angelo";
profile.isbald = false;

console.log(profile);


javascript中有这个object,我们可以用它来对对象变量进行键到值的映射、获取键、获取值等功能。它有一些方法,例如条目(objectvariable),键(objectvariable)和值(objectvariable)。


console.log(object.entries(profile));
//it has created an array of the key and value
// [
//   [ 'name', 'john doe' ],
//   [ 'date of birth', '2000-12-25' ],
//   [ 'profession', 'software engineer' ],
//   [ 'number of pets', 2 ],
//   [ 'weight of protein in grams', 12.5 ],
//   [ 'has a job', true ]
// ]

console.log(object.keys(profile));
//it returns the keys of the object as an array
// [
//   'name',
//   'date of birth',
//   'profession',
//   'number of pets',
//   'weight of protein in grams',
//   'has a job'
// ]

console.log(object.values(profile));
//it returns the values of the object as an array
// ["john doe", "2000-12-25", "software engineer", 2, 12.5, true];


还有更多,不过,目前我认为这已经足够了。

大批

数组是一个列表或项目的集合。由于这是 javascript,我们可以列出任何内容,也可以不列出任何内容。我们可以有一个数字、字符串、布尔值等的数组

在 javascript 中,我们可以使用方括号来创建数组。我们讨论的所有关于变量和值的内容都适用于数组。字符串中的一些知识可能适用(借用的知识)。

示例


// an empty array
const anemptyarray = [];

// array of numbers
const arrayofnumbers = [1, 2, 3, 4, 5];

// array of strings
const stringarray = ["math", "meth", "mith", "moth", "muth"];

const listofblacklistedusers = [
  "adamdoe",
  "peterpen",
  "maxbuffer",
  "cheesecake",
  "paxtingaa",
];

// array of booleans
const booleanarray = [true, false, false, true, true];

// const array of objects
const profilearray = [
  { id: 1, username: "adamdoe", pet: "math", isbald: true },
  { id: 2, username: "peterpen", pet: "meth", isbald: false },
  { id: 3, username: "maxbuffer", pet: "mith", isbald: false },
  { id: 4, username: "cheesecake", pet: "moth", isbald: true },
  { id: 5, username: "paxtingaa", pet: "muth", isbald: true },
];

// array of arrays
const threebythreesudoku = [
  [4, 9, 2],
  [3, 5, 7],
  [8, 1, 6],
];


索引数组

我们在字符串部分讨论的索引概念适用于此。索引从零开始。

示例


const evennumbers = [2, 4, 6];

const firstevennumber = evennumbers[0];
const secondevennumber = evennumbers[1];
const thirdevennumber = evennumbers[2];

const sumofevennumbers = firstevennumber + secondevennumber + thirdevennumber;
const productofevennumbers =
  firstevennumber * secondevennumber * thirdevennumber;

console.log(
  `the sum and product of the even numbers, ${evennumbers} are, ${sumofevennumbers} and ${productofevennumbers} respectively`
);
// the sum and product of the even numbers, 2,4,6 are, 12 and 48 respectively


数组属性和方法

数组和字符串一样,也有可以使用点运算符、arrayvariable.propertyname 和 arrayvariable.methodname(someargs) 访问的属性和方法;

这些是我专业使用过的一些属性和方法。有很多,但我会提到一些并演示如何使用它们。

  • length (p): arrayvariable.length 返回数组的长度(元素数量)。

const stringarray = ["math", "meth", "mith", "moth", "muth"];

// get the length of an array
console.log(
  `there are ${stringarray.length} elements in the array, ${stringarray}`
);


  • push(m):接收一个值并将其添加到原始数组中。要知道这会改变数组。

const numbers = [1, 2, 3, 4, 5];
console.log(numbers);
console.log(numbers.length);

// add an element at the end of the array
numbers.push(-1);
console.log(numbers);
console.log(numbers.length);


  • pop(m):从数组中删除最后一个元素并返回它。因此,您可以抢救最后一个元素并将其用于某些计算。

const numbers = [1, 2, 3, 4, 5];
console.log(numbers);
console.log(numbers.length);

// returns the last element from the array
const poppednumber = numbers.pop();
console.log(`${poppednumber} was popped from the array`);
console.log(numbers);
console.log(numbers.length);


  • map (m):返回一个与原始数组大小相同的新数组,并根据数组元素进行一些计算。 map方法的签名为 (callbackfn: (value: elementtype, index: number, array: elementtype[]) => callbackfnreturntype, thisarg?: any):callbackfnreturntype[].

    • callbackfn:代表回调函数,一个作为参数传递的函数(作为某个东西的值,这里是map方法)
    • callbackfn 接受值、索引和数组作为参数。回调函数的值(第一个参数和必需参数)引用数组中的一个元素。索引指的是该元素的索引。数组参数(可以是任何名称)引用原始数组的副本。
    • 回调函数应用于数组的每个元素
    • 对于我们的用例,我们需要值,有时还需要索引。

const stringarray = ["math", "meth", "mith", "moth", "muth"];

const uppercasestringarray = stringarray.map((value, index, thearray) => {
  return value.touppercase();
});
console.log(uppercasestringarray);
// [ 'math', 'meth', 'mith', 'moth', 'muth' ]


本例中未使用索引和 thearray 值。我会修改map方法的使用。


const stringarray = ["math", "meth", "mith", "moth", "muth"];
const uppercasestringarray = stringarray.map((value) => value.touppercase());
console.log(uppercasestringarray);


我们能用数学函数做的事情受到我们目前知识的限制。

请记住,=> 返回用于形成数组的新值。

  • filter (m):filter 方法的功能类似于 map 方法,但是它返回满足条件的元素数组(一些真值声明 - 返回布尔值)。

const elementinnature = ["water", "earth", "wind", "fire"];

// filter elements that include 'a'
const elementsthatincludea = elementinnature.filter((value) =>
  value.includes("a")
);
console.log(elementsthatincludea);

// filter elements that end with 'er'
const elementsthatendswither = elementinnature.filter((value) =>
  value.endswith("er")
);
console.log(elementsthatendswither);


  • reduce(m):像filter和map一样,对每个元素应用一个函数。但是,它返回一个值而不是数组。它将数组“减少”为单个值。 reduce方法的签名与map和reduce方法的签名几乎相同。但是,reduce 接受另一个必需参数,即先前的值。 reduce<u>(callbackfn:(previousvalue:reducetotype,currentvalue:elementtype,currentindex:number,array:elementtype[])=>reducetotype,initialvalue:reducetotype):reducetotype;。此时最好使用示例。

const numberarray = [4, 6, 5, 9, 2, 8];
const sumofnumbers = numberarray.reduce((prev, curr) => prev + curr, 0);
console.log(numberarray);
console.log(sumofnumbers);


我们将初始值设置为零。由于循环从第一个值开始,因此不会定义前一个值(或默认为零)。我们可以选择将其设置为另一个号码。尝试一下,看看结果。

让我使用更多伪代码来重写它,例如:


 const result = somearray.reduce((initial value, current value)=> some action involving the previous value and current value, set the initial value to be something here)


还有一个


 const result = somearray.reduce((expected result, current value)=> some action involving the previous value, which is the expected value, and current value, set a default value for the expected result here)


  • include (m):返回一个布尔值,指示数组中是否存在某个元素。它与字符串.

    聚好用AI
    聚好用AI

    可免费AI绘图、AI音乐、AI视频创作,聚集全球顶级AI,一站式创意平台

    下载
  • 的includes方法相同
  • join (m):将数组中的元素用分隔符组合成一个字符串。 join 方法采用分隔符参数。这是一个字符串。


const numberarray = [4, 6, 5, 9, 2, 8];

console.log(numberarray.join(""));
// 465928
console.log(numberarray.join("_"));
// 4_6_5_9_2_8
console.log(numberarray.join("000"));
// 400060005000900020008


我们可以用字符串和数组做一些很棒的事情。

  • find(m):与map、filter的参数格式相同。它返回满足条件的第一个元素,否则返回未定义。有一个很好的地方可以使用find代替filter。稍后会详细介绍。

展望未来

我们可以在下一部分中做类似的事情。

考虑用户配置文件数组。


const profilearray = [
  { id: 1, username: "adamdoe", pet: "math", isbald: true },
  { id: 2, username: "peterpen", pet: "meth", isbald: false },
  { id: 3, username: "maxbuffer", pet: "mith", isbald: false },
  { id: 4, username: "cheesecake", pet: "moth", isbald: true },
  { id: 5, username: "paxtingaa", pet: "muth", isbald: true },
];


我们可以使用过滤器来查找用户名中包含“a”或“a”的用户。


const userswitha = profilearray.filter((user) =>
  user.username.tolowercase().includes("a")
);


我们不会通过控制台记录整个对象,而是只记录他们的用户名。


const usernameswitha = userswitha.map((user) => user.username);
console.log(usernameswitha);


我们分别执行这些操作,但是,我们可以通过链接将它们组合在一起。


const usernameswitha = profilearray
  .filter((user) => user.username.tolowercase().includes("a"))
  .map((user) => user.username);

console.log(usernameswitha);
// [ 'adamdoe', 'maxbuffer', 'cheesecake', 'paxtingaa' ]


过滤器和映射中使用的用户变量可以是任何其他变量名称。我选择用户是因为它为我们正在做的事情添加了背景。

知道我们也可以在过滤器方法之前调用映射方法,并且我们会得到相同的输出。然而,我们必须小心。在map方法中,我们正在访问用户名属性(键),因此从map方法返回的数组将是一个字符串数组,而不是具有多个属性的对象。


const usernameswitha = profilearray
  .map((user) => user.username)
  .filter((username) => username.tolowercase().includes("a"));

console.log(usernameswitha);
// [ 'adamdoe', 'maxbuffer', 'cheesecake', 'paxtingaa' ]

//we listed the username, then filtered out usernames that included 'a'


我们可以使用find方法来查找第一个收入超过20万的光头用户。


const exclusiveusers = profilearray
  .filter((user) => user.isbald)
  .filter((user) => user.salary > 200000)
  .map((user) => user.username);

console.log(exclusiveusers);
// [ 'adamdoe', 'paxtingaa' ]


因为我们正在寻找第一个用户,所以我们可以做,exclusiveusers[0],当我们控制台记录它时,它应该是adamdoe

在接下来的部分中,我们将学习足够的知识来使用一种过滤方法而不是两种或多种。


const exclusiveusers = profilearray
  .filter((user) => user.isbald && user.salary > 200000)
  .map((user) => user.username);

console.log(exclusiveusers[0]);
// adamdoe


&& 表示“and”,并且 > 大于号。他们都是运营商。我们将更多地讨论它们,并简单或相当现实地重做一些示例。

我们想使用查找而不是过滤。我们提到 find 返回元素。它不会像 map 或 filter 方法那样返回数组。要知道结果可能是未定义的,这意味着在数组中找不到与真值语句(谓词或条件)匹配的值。我们指的条件是 user.isbald && user.salary > 200000,用户是秃头(isbald 将为 true)并且用户的工资超过 200000,(工资值大于 200000)。


const exclusiveuser = profilearray.find(
  (user) => user.isbald && user.salary > 200000
);

console.log(exclusiveuser);
// {
//   id: 1,
//   username: 'adamdoe',
//   pet: 'math',
//   isbald: true,
//   salary: 250000
// }

// since we are interested in the username, we can do
console.log(exclusiveuser.username);
// adamdoe


我们有一个复杂的主体或回调函数,我们可以使用 return 代替 => (粗箭头运算符)。但是我们必须注意并添加左大括号和右大括号 { 和 }。

现在让我们考虑一下我们想要通过添加新字段来更新用户个人资料的情况。


const exclusiveusers = profilearray.map((user) => {
  user.username = user.username.touppercase();
  user.isexclusive = user.isbald && user.salary > 200000;

  return user;
});
console.log(exclusiveusers);

// [
//   {
//     id: 1,
//     username: 'adamdoe',
//     pet: 'math',
//     isbald: true,
//     salary: 250000,
//     isexclusive: true
//   },
//   {
//     id: 2,
//     username: 'peterpen',
//     pet: 'meth',
//     isbald: false,
//     salary: 658000,
//     isexclusive: false
//   },
//   {
//     id: 3,
//     username: 'maxbuffer',
//     pet: 'mith',
//     isbald: false,
//     salary: 850000,
//     isexclusive: false
//   },
//   {
//     id: 4,
//     username: 'cheesecake',
//     pet: 'moth',
//     isbald: true,
//     salary: 90000,
//     isexclusive: false
//   },
//   {
//     id: 5,
//     username: 'paxtingaa',
//     pet: 'muth',
//     isbald: true,
//     salary: 366000,
//     isexclusive: true
//   }
// ]


我们将用户名更新为大写,并添加了一个新密钥,表明该用户(个人资料)是独占的。

我们可以计算平均工资,并过滤掉那些收入高于平均工资的人。


const numberofusers = profilearray.length;
const totalsalaries = profilearray.reduce(
  (total, currentuser) => total + currentuser.salary,
  0
);
const averagesalary = totalsalaries / numberofusers;
console.log(
  `the average salary of ${numberofusers} users with a combined total of ${totalsalaries} is ${averagesalary}`
);
// the average salary of 5 users with a combined total of 2214000 is 442800

// now let's filter the above average salary users
const aboveaveragesalaryusers = profilearray.filter(
  (user) => user.salary > averagesalary
);
console.log(
  `${aboveaveragesalaryusers.length} users who earn above the average salary of ${averagesalary}`
);
// 2 users who earn above the average salary of 442800

// we will get their user names

const combinedusernames = aboveaveragesalaryusers
  .map((user) => user.username)
  .join(" and ");
console.log(`these users are ${combinedusernames}`);
// these users are peterpen and maxbuffer


我们将在接下来的函数部分了解更多关于函数以及函数参数和实参的知识。 我们还将讨论 return 关键字和注释。

电子邮件验证

这是我对上一节中的电子邮件验证的实现。这些是电子邮件验证的规则。电子邮件必须:

  • 至少十六个字符
  • 全部小写
  • 其中没有“电子邮件”
  • 不包含下划线
  • 有一个“@”
  • 有一个“.”
  • 以“.com”结尾
  • 有'@'之前的字符为字符,大写v,'v'

示例


<p>// email_validation.js<br>
const sampleEmail = "johndoe@email.com";<br>
// Email must:<br>
// - be at least sixteen characters<br>
const emailLength = sampleEmail.length;<br>
console.log(<br>
  - Email must be at least sixteen characters => "</span><span class="p">${</span><span class="nx">sampleEmail</span><span class="p">}</span><span class="s2">" has '</span><span class="p">${</span><span class="nx">emailLength</span><span class="p">}</span><span class="s2">' characters<br>
);</p>

<p>// - be in all lowercase<br>
// There could be split opinions, either force the users to enter their<br>
// emails in lowercase or cast it to lowercase. The latter seems better<br>
const lowercasedEmail = sampleEmail.toLowerCase();<br>
// or can use the sampleEmail.toLowerCase() from here onwards</p>

<p>// - not have 'email' in it<br>
const hasEmail = lowercasedEmail.includes("email");<br>
// If hasEmail is true then this email is invalid<br>
console.log(<br>
  - Email must not have 'email' in it => It is '</span><span class="p">${</span><span class="nx">hasEmail</span><span class="p">}</span><span class="s2">' that "</span><span class="p">${</span><span class="nx">lowercasedEmail</span><span class="p">}</span><span class="s2">" has 'email' in it<br>
);</p>

<p>// - not include an underscore<br>
const hasUnderscore = lowercasedEmail.includes("_");<br>
console.log(<br>
  - Email must not include an underscore => It is '</span><span class="p">${</span><span class="nx">hasUnderscore</span><span class="p">}</span><span class="s2">' that "</span><span class="p">${</span><span class="nx">lowercasedEmail</span><span class="p">}</span><span class="s2">" includes an underscore<br>
);</p>

<p>// - have one '@'<br>
const hasAtSymbol = lowercasedEmail.includes("@");<br>
console.log(<br>
  - Email must have one '@' => It is '</span><span class="p">${</span><span class="nx">hasAtSymbol</span><span class="p">}</span><span class="s2">' that "</span><span class="p">${</span><span class="nx">lowercasedEmail</span><span class="p">}</span><span class="s2">" has one '@;<br>
);</p>

<p>// get the index of the first at<br>
const indexOfFirstAtSymbol = lowercasedEmail.indexOf("@");<br>
console.log(The index of the first '@' is at: </span><span class="p">${</span><span class="nx">indexOfFirstAtSymbol</span><span class="p">}</span><span class="s2">);<br>
// the output from above will let us know if there is even an '@'<br>
// the index must not be -1</p>

<p>// lowercasedEmail.includes("@") and lowercasedEmail.indexOf("@")<br>
// shows that there is an '@' but not how many</p>

<p>// if there is more than one '@' then when we split the email,<br>
// there will be more than two elements<br>
// when you split in the middle (one part), you get 2 parts<br>
// when you split at 2 parts, you get 3 parts<br>
const arrayLengthAfterSplitting = lowercasedEmail.split("@").length;<br>
console.log(<br>
  The number of elements after the email is split at the '@' is: </span><span class="p">${</span><span class="nx">arrayLengthAfterSplitting</span><span class="p">}</span><span class="s2"><br>
);</p>

<p>// there is the lastIndexOf string method, which returns the last occurrence<br>
// of a substring in a string</p>

<p>// - have one '.'<br>
const arrayLengthAfterSplittingAtDot = lowercasedEmail.split(".").length;<br>
console.log(<br>
  The number of elements after the email is split at the '.' is: </span><span class="p">${</span><span class="nx">arrayLengthAfterSplittingAtDot</span><span class="p">}</span><span class="s2"><br>
);</p>

<p>// - end with '.com'<br>
const emailEndsWithDotCom = lowercasedEmail.endsWith(".com");<br>
console.log(<br>
  - Email ends with '.com' => It is '</span><span class="p">${</span><span class="nx">emailEndsWithDotCom</span><span class="p">}</span><span class="s2">' that "</span><span class="p">${</span><span class="nx">lowercasedEmail</span><span class="p">}</span><span class="s2">" ends with '.com'<br>
);</p>

<p>// - have the character before the '@' to be the character, uppercase v, 'V'<br>
// the character before the '@' is at index, '@' index - 1<br>
const characterBeforeAt = lowercasedEmail.charAt(indexOfFirstAtSymbol - 1);<br>
console.log(<br>
  - Email must have the character before the '@' to be the character, uppercase v, 'V' => The character before the '@' is '</span><span class="p">${</span><span class="nx">characterBeforeAt</span><span class="p">}</span><span class="s2">'<br>
);</p>




结论

数组很有用,数组方法可以更轻松地按照我们认为合适的方式操作数据。随着新概念的加入,我们现在可以做更多的事情。尝试使用数组和字符串方法重写密码和电子邮件验证。

我们还有更多关于 javascript 的内容可以讨论,例如:

  • 传播和解构
  • 运营商
  • 控制结构(if 语句、循环)
  • 功能
  • 回调、承诺、异步和等待
  • 下一件大事

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

241

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

150

2025.10.17

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

847

2023.08.22

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

761

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

221

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1570

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

651

2023.11.24

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

49

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
尚学堂ios初级视频教程
尚学堂ios初级视频教程

共77课时 | 18.4万人学习

第三期培训_PHP开发
第三期培训_PHP开发

共116课时 | 27.7万人学习

PHP零基础通关宝典
PHP零基础通关宝典

共78课时 | 10.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号