🦄 2024 独立开发者训练营,一起创业!查看介绍 / 立即报名(剩余10个优惠名额) →

Node.js 服务端应用开发 #3:JavaScript 程序设计语言基础

开发语言(程序语言)是一种写作语言,不同的开发语言都有各自的书写方法,如果你想用某种开发语言表达自己的想法,开发应用,就需要了解这种语言规定的书写方法,也就是语法。

一开始,不推荐大家在学习书写方法这种事儿上花太多的时间,只需要了解一些基本的写法就可以了,剩下的可以在实际工作中学习,带着需求去学习,效率会更高。不同的开发语言虽然各有不同,但很多概念都是通用的,所以只要学会其中一门开发语言,再去学习其它的语言就很容易了。

在这一章里,我们先做一些基础的语言训练,了解一下在任何开发语言中都可能会经常出现的一些概念,这样再去做后面的任务就会轻松很多。

语言训练场地

现在我们要学习的是 JavaScript 这种开发语言,找个可以运行这种语言的环境就可以学习它了。浏览器里都带着一个 JavaScript 引擎,所以可以在浏览器上学习这门语言。 之前我们在本地电脑上安装过一个 Node.js,所以也可以在这个环境里学习 JavaScript 这门开发语言。

如果选择在浏览器上学习,推荐使用 Chrome 浏览器,打开浏览器以后,再打开它的开发者工具,然后打开 Console(控制台)这个选项卡,这样就可以直接在控制台上执行 JavaScript 代码,而且可以立即得到执行的结果。

安装了 Node.js 以后,在终端,执行一下 node 命令,可以打开 Node.js 的交互模式,在这种模式下就可以输入并且执行 JavaScript,也可以立即看到执行的结果。我们也可以在项目里创建一些文件,把代码放在文件里,再到终端用 node 命令执行代码文件,观察执行的结果。

控制台:Console

在应用里有些东西你可能不会马上知道它里面到底有什么,这时我们就可以通过 console.log() 这个方法,把它输出到控制台上检查一下,所以控制台应该是最简单的调试应用的地方。

在开发浏览器应用(前端)的时候,控制台指的是浏览器的开发者工具里的 Console 选项卡,在开发 Node.js 应用的时候,控制台指的就是运行应用的终端窗口。

示例:

console.log('你好!');

如果在应用里包含上面这行代码,运行这个应用的时候,在控制台就会输出一个 你好!

数据:Data

在开发应用的时候会用到一些不同类型的数据,比如数字,字符串,数组,对象,布尔值这些都是常见的数据类型。我们可以给数据起个名字,这样以后需要用到这个数据的时候,就可以使用它的名字来表示它了,数据名字的专业称呼是常量(Constant)或者变量(Variable)。

创建一个常量或者变量,这个动作叫声明,声明一个常量或变量,其实就是在内存里申请一小块儿空间来存储数据。给这块空间起个名字(Identifier),以后就可以用这个名字来引用存储在这小块空间里的数据了。

常量:Constant

在 JavaScript 语言里,声明一个常量用的是 const 这个关键词,取的是 Constant(常量) 这个词的一部分。常量的特点是一但声明了一个常量,给它分配了一个值以后,就不能再分配给这个常量新的值了,这就是常量与变量的区别。

示例:

const title = '小白兔的开发之路';

上面创建(声明)了一个叫 title 的常量,给它分配了一个字符串类型的值:小白兔的开发之路。重新给已经声明的常量分配新的值,应用就会报错:TypeError: Assignment to constant variable 。

变量:Variable

在用 JavaScript 语言写的应用里添加一个变量,用的是 let 关键词,也可以用 var 这个关键词。声明了一个变量,给它分配了值以后,可以重新改变它的值。

示例:

let page = 1;

上面用 let 声明了一个叫 page 的变量,给它分配了一个数字类型的值:1。我们可以重新给它一个新的值:

page = 2;

现在 page 的值就会变成数字 2 了。

字符串:String

字符串是在应用里常见的数据类型,字符串就是文字。在 JavaScript 语言里,这种类型的数据一般会用双引号或者单引号包装一下。把一些文字用引号包装一下,把它交给一个常量或者变量,JavaScript 就会认为这个常量或者变量的值的类型是字符串。

示例:

const author = '王皓';

上面声明了一个叫 author 的常量,给它一个字符串类型的值:王皓

数字:Number

数字也是在应用里经常出现的一种数据类型,如果你发现在应用里出现了一些数字,这些数字的周围并没有使用特别的符号(比如引号)包装,那这个数字就是一个数字类型的值。

示例:

const price = 39.9;

上面声明了一个叫 price 的常量,给它的是个数字类型的值:39.9 。

数组:Array

数组指的就是一组数据,就是在一个数组里面可以包含多个数据项目,这些数据项目的类型可以是不一样的,可以是数字,字符串,也可以是其它的数组。通过一些方法我们可以往现有的数组里面添加新的数据项目,也可以删除掉数组里的数据项目。

数组里包含的数据项目是有顺序的,序号是从 0 开始的,也就是第一个项目的序号是 0,第二个项目的序号是 1,依次往后面排。这个序号也可以称为索引号,英文是 Index。通过数组里的数据项目的序号我们就可以获取到这个数据项目的值。

在 JavaScript 语言里,数组可以使用一组方括号来表示,里面的每个数据项目之间用逗号分隔开。

示例:

const chapters = ['准备开发', '管理代码', '熟悉语言'];

上面声明了一个叫 chapters 的常量,它的值是一个数组,这个数组里有三个字符串类型的数据项目。如果你想得到这个数组里的第一个数据项目的值,可以用 chapters[0] 得到,数组的名字,后面加上一组方括号,方括号里面是数据项目的序号。在这个例子里,访问 chapters[0] 得到的就是一个字符串:'准备开发 ' 。

JavaScript 为处理数组类型的数据提供了很多个方法,所有的数组数据天生就拥有这些方法。比如我要上面这个数组里添加一个新的数据项目,可以用 push() 这个数组方法:

chapters.push('提供服务');

现在 chapters 这个数组里就会有 4 个数据项目了,它们是:

['准备开发', '管理代码', '熟悉语言', '提供服务'];

这种处理数组用的方法有几十个,我们不需要一下子记住所有这些方法,当遇到问题的时候可以去寻找对应的方法。想了解更多,可以搜索关键词:MDN Array 。

对象:Object

一个对象就是一个物件,一个东西,英文用 Object 来表示。在程序里我们可以通过对象来描述一种东西,比如一篇文章,一个评论,一个用户等等。对象里可以包含一些属性还有方法(函数),属性相当于是这个东西的数据,方法相当于是这个东西可以做的事情。

在 JavaScript 语言里,对象可以放在一组大括号里,它里面是一些属性,属性有名字还有对应的值,中间用冒号分隔开,属性与属性之间会用逗号分隔开。创建一个对象,用它来表示一本书,可以像下面这样:

const book = {  
  title: '小白兔的开发之路',
  price: 39.9,  
  chapters: ['准备开发', '管理代码', '熟悉语言'],
};

上面声明了一个常量叫 book,给它的这个值,类型是对象。这个对象里面有几个属性:titleprice 还有 chapters。得到对象里的属性的值,使用对象里提供的方法,都可以使用点的形式,比如得到 book 这个对象里的 title 属性的值,可以这样:book.title ,得到的就是:'小白兔的开发之路 ' 。

布尔值:Boolean

布尔值只有两个选择:true 与 false。真的假的,有值没值,有效无效,这些情况用布尔值表示的话就是 true 与 falsetrue 就是真的,有值,有效 ... false 指的就是假的,没值,无效,0 ...

字符模板:Template strings

使用字符模(mú)板可以更方便的组织文字,字符模板用的是一组反引号( ` ),在字符模板中要输入的值可以放在 ${} 的大括号里面。

示例:

const title = '小白兔的开发之路';
const author = '王皓';

const description = `《 ${title} 》,作者:${author}`;

上面这个例子里,description 的值用了一个字符模板,里面插入了 title 与 author 的值,最终它的值应该是:《 小白兔的开发之路 》,作者:王皓 。

反引号 ` 在键盘上一般跟波浪号 ~ 在同一个按键上。

函数:Function

我们可以把一块儿代码组织在一起,定义成一个函数,可以给它起个名字,这样就可以重复执行它。

创建函数

创建一个函数可以使用 function 这个关键词,后面是要创建的函数的名字,函数也可以没有名字。然后是一组括号,括号里面可以添加函数里面需要的一些参数,接着是一组大括号,把函数要做的事情放在这组大括号里面。

示例:

function log() {
  console.log('LOG::');
}

上面用 function 定义(声明)了一个叫 log 的函数,这里我们只是简单的用了一个 console.log() 在控制台上输出点内容。

箭头函数

使用 **=> **(胖箭头)的形式也定义函数,箭头的左边儿是函数的参数,右边儿是函数的主体,也就是函数要做的事情。这些事情可以放在一组大括号里面,不过如果函数主体只有一行代码,就不需要用大括号了。

示例:

const log = () => {
  console.log('LOG::');
};

在上面我们把用箭头形式定义的函数交给了 log 这个常量,也就是 log 的值是一个函数。

执行函数

要使用函数提供的功能,就需要执行一下这个函数。执行函数可以使用函数的名字,后面加上一组括号。

示例:

log();

函数参数

在定义函数的时候可以添加一些参数(Arguments),在函数的主体里面可以使用这些参数,然后在执行函数的时候可以设置这些参数的具体的值。这些参数就相当于是函数的配置信息,函数可以重复使用,每次执行它的时候都可以提供不同的参数的值,这样执行的结果也就会不一样了,也就是参数可以让函数更加灵活。

示例:

function log(message) {
  console.log('LOG::', message);
}

箭头函数:

const log = message => {
  console.log('LOG::', message);
};

在上面定义的函数里面都添加了一个参数,参数的名字是 message,这样在函数的主体里面就可以使用这个参数了。执行函数的时候需要提供函数的参数具体的值。

执行函数的时候,可以设置函数的参数值把,把要提供的参数值按顺序放在括号里,像这样:

log('hello ~');

上面在使用 log() 函数的时候,给它的 message 参数提供的值是 hello ~,执行这个函数输出的结果就会是:LOG:: hello ~

log('你好!');

这次我们在用 log() 函数的时候,给它的 message 参数提供的值是 *你好!*所以,执行这个函数输出的结果会是:LOG:: 你好!

多个参数

函数可以支持多个参数,这些参数之间用逗号分隔开,执行函数提供参数值的时候要按参数的顺序。

示例:

const log = (message, prefix) => {
  console.log(prefix, message);
};

在上面定义的 log() 函数里面,设置了两个参数:message 与 prefix。在执行这个函数的时候,提供给它的第一个参数值是为 message 准备的,提供的第二个参数的值会交给 prefix 。

执行:

log('你好!', '日志::');

在上面执行 log() 函数的时候给它的两个参数都提供了具体的值,你好! 是给 message 参数的值,日志:: 是给 prefix 这个参数的值。执行的结果就是在控制台上输出了:日志:: 你好!

返回结果

如果想利用执行函数以后得到的结果,在定义这个函数的时候就需要让它返回一个结果。在函数的主体里,可以使用 return 这个关键词返回一个结果。

示例:

const greet = name => {
  return '你好!' + name;
};

上面定义的 greet() 函数会返回(Return)它加工处理之后的结果,这里返回就是 你好! 再加上执行 greet() 函数的时候给 name 参数提供的值。

这个函数是用胖箭头的形式定义的,函数很简单,支持一个参数,函数的主体也只有一行,这样情况下,定义这个箭头函数的时候可以简化成一行代码,像这样:

const greet = name => '你好!' + name;

执行:

const greeting = greet('王皓');

因为 greet() 函数可以返回它制造出来的结果,所以可以把这个结果交给别人(常量或变量),这里我们把它交给了一个叫 greeting 的常量,它的值是:你好!王皓,因为这就是执行 greet() 函数得到的结果。

方法:Method

函数如果出现在一个对象里,可以说它是这个对象里的一个方法(Method)。

示例:

const book = {
  title: '小白兔的开发之路',
  toString() {
    return `《${this.title}》`;
  },
};

book 是个对象,里面有个 title 属性,还有一个 toString() 方法,这个方法其实就是一个函数。在这个 toString() 方法里,用了 this 这个关键词,它指的是这个对象本身。

使用这个对象里的方法,可以这样:

book.toString();

解构:Destructuring

拆开一个数组或者对象,把它们里面的值交给各自的常量或变量,这就是解构这种写法。

示例<解构对象>:

const book = {
  title: '小白兔的开发之路',
  author: '王皓',
};

上面的 book 是个对象,假设我现在需要声明两个常量:title 与 author,让 title 的值等于 book 对象里的 title 属性的值,让 author 的值等于 book 里的 author 属性的值。

如果不用解构的写法,应该像这样:

const title = book.title;
const author = book.author;

使用解构的写法,可以这样:

const { title, author } = book;

意思就是拆开 book 对象的值,把 title 属性的值交给 title 常量,把 author 属性的值交给 author 常量。使用解构的写法定义常量或变量的时候,它们的名字应该跟对象里的属性的名字一致,如果你想使用其它的名字,也可以重新命名一下,用下面这种写法:

const { title: titleAlias } = book;

上面这行代码会声明一个叫 titleAlias 的常量,它的值是 book 对象里的 title 属性的值。

const fruits = ['苹果', '香蕉', '桔子'];

解构上面这个 fruits 数组,可以像这样:

const [c1, c2, c3] = fruits;

c1c2 还有 c3 的值分别对应的是 fruits 数组里的第一个,第二个还有第三个项目的值。

展开:Spread

展开,有点像是脱掉数组或者对象的 “壳”,留下它们里面的 “瓤”,我们可以再把得到的这个 “瓤” 放在别人那里。展开操作符是三个点( ... ),把要展开的东西放在这个展开操作符的后面就行了。要展开的东西可以是数组,也可以是个对象。

示例:

const fruits = ['苹果', '香蕉', '桔子'];
const vegetables = ['土豆', '茄子', '辣椒'];

上面定义的是两个数组。假设我们要创建一个新的东西,里面包含 fruits 与 vegetables 这两个数组里所有的项目,用展开(Spread)这种写法可以这样做:

const food = [...fruits, ...vegetables];

上面这个 food 是个数组,这个数组里会包含在 fruits 与 vegetables 里面所有的项目。

['苹果', '香蕉', '桔子', '土豆', '茄子', '辣椒'];
const data = {
  title: '小白兔的开发之路',
};

const author = {
  name: '王皓',
};

创建一个新的对象,里面需要上面这个 data 对象里的所有属性,还需要一个 author 属性,对应的值就是上面这个 author 对象。

const book = {
  ...data,
  author,
};

上面新建的这个 book 对象,应该像下面这样:

{
  title: '小白兔的开发之路',
  author: {
    name: '王皓',
  }
}

流程控制:Control flow

JavaScript 语言提供了一些方法可以控制代码的执行顺序,下面我们就来学几种常用的方法。

if

检查一个条件,满足条件时执行一块儿代码。

写法 1:

判断一个指定的条件,如果情况符合这个条件,就去执行指定的代码。

if () {}

用 if 这个关键词,然后在它后面的括号里可以设置一个条件,满足这个条件时可以执行大括号里的代码。

示例:

if (speed > 120) {
  console.log('您已超速!');
}

检查 speed 的值是否大于 120,如果符合这个条件,也就是条件表达式返回的值是 true ,就会执行在 if 后面的大括号里的代码,也就是在控制台上输出:您已超速!

写法 2:

检查一个条件,满足条件时执行一块儿代码,不满足时执行另外一块儿代码。

if () {

} else {

}

示例:

if (speed > 120) {
  console.log('您已超速!');
} else {
  console.log('车速正常~');
}

如果车辆的时速大于 120,就会输出:*您已超速!*不然的话就输出:车速正常~

switch

检查一个值,设置一些情况,执行不同的代码。

写法:

switch () {
  case :

    break;
  case :

    break;
  default:

    break;
}

把要检查的值放在 switch 后面的括号里,再把所有的情况都放在一组大括号里,用 case 可以添加一种情况,case 的下面是符合当前这种情况之后要做的事情,在设置的情况里面用了 break,这样满足这种情况以后,就会 break 出来,也就不会继续检查其它的情况了,就是从这个 switch 里跳出来。

示例:

let gear = 'P';

上面的 gear 表示车子的档位,我想根据当前档位的值去做不同的事情。如果用 if 这种写法,会像这样:

if (gear === 'P') {
  console.log('停车');
}

上面判断了 gear 的值是不是等于 P,如果是就在控制台上输出 停车。用这种写法你可能要写很多个 if ,因为有很多种要判断的条件。如果换成 switch 这种写法,会像下面这样:

switch (gear) {
  case 'P':
    console.log('停车');
    break;
  case 'R':
    console.log('倒车');
    break;
  case 'D':
    console.log('开车');
    break;
  case 'N':
    console.log('空档');
    break;
  default:
    console.log('档位异常!');
    break;
}

在上面这个例子里,用 switch 检查了一下 gear 表示的值,用 case 设置了一些情况,如果 gear 的值是 P ,就执行 case 'P' 这种情况下设置的代码,如果是 R ,就执行 case 'R' 这种情况下设置的代码。如果 gear 的值不满足所有列出的情况,就会执行默认情况(default)下的代码。不需要这种默认的情况,可以不必使用这个 default 。

throw

应用在运行的时候可能会发生一些异常情况,比如你定义了一个函数,它的作用就是往数据仓库里存储数据,非常有可能在执行这个函数的时候会遇到一些异常的情况,比如数据仓库正好不能用了。我们可以在函数里判断一下,如果在存储数据的时候,发生了这些异常情况,就用 throw 来触发一个异常。在使用这个函数的时候,可以设置一下处理执行这个函数的时候可能会发生的异常情况。

在函数里出现的异常情况,可以用 throw 这个关键词来触发异常,这样函数就会停止执行, throw 下面的代码都不会被执行,如果没有处理这个异常,应用也会停止运行。

示例:

const drive = () => {
  throw new Error('没油了!');
};

drive();

上面定义了一个叫 drive() 的函数,函数里直接用 throw 抛出一个叫 Error 的异常,在 Error() 里添加的字符串是异常信息。执行 drive() 这个函数,应用就会抛出一个异常,应用会停止运行。

try...catch

试着去做一些事情,如果出现异常再处理发生的异常。

写法:

try {

} catch() {

}

在要做的事情放在 try 区块里面,如果在做的这些事情里发生了异常情况,可以在 catch 区块里处理发生的异常。

示例:

const getGasoline = () => {
  return false;
};

const drive = () => {
  const gasoline = getGasoline();

  if (!gasoline) {
    throw new Error('没油了!');
  }

  console.log('呜~呜~~~');
};

try {
  drive();
} catch (error) {
  console.log(error.message);
}

上面定义了两个函数,getGasoline() 与 drive(),然后执行了 drive() 函数。getGasoline() 函数的功能是获取汽车的油量,为了演示异常,我们让它一直返回 false。在 drive() 函数里,先用了一下 getGasline() 获取油量,然后判断了一下,如果汽车没油了,就用 throw 抛出一个异常。不然就在控制台上输出 呜~呜~~~

执行 drive() 函数的时候我们把它放在了 try 区块里,这样执行这个函数如果发生了异常,可以在 catch 区块里处理,这里就是在控制台上,输出了 error 对象里的 message 属性的值。

因为 getGasoline() 这个函数会一直返回 false 值,所以执行 drive() 函数就一定会出现异常。也就是如果执行上面这段代码,你会在控制台上看到 没油了! 这几个字儿。如果我们修改 getGasoline() 函数,让它返回 true ,执行上面这块代码会在控制台上输出 呜~呜~~~

类:Class

类(Class)是对象(Object)的模板。定义一个类,在它里面添加属性与方法,然后基于这个类可以去创建一些对象,这些对象里会拥有类里的属性与方法。

创建类

创建一个类,可以用 class 关键词,后面加上类的名字就行了,类里的东西放在一组大括号里。类的名字一般会选择首字母大写,比如我要创建一个 “用户服务 ” 这个类,用户的英文是 User,服务的英文是 Service,所以这个类的名字就可以是 UserService,当然 JavaScript 并不会限制你到底为类取什么名字,你觉得合理就行。

写法:

class ClassName {}

示例:

class Car {}

上面声明(定义、创建)了一个类,名字是 Car(汽车),这是一个空白的类,里面啥都还没有呢。

实例化

基于类去创建对象,这个动作叫实例化(Instantiate),创建的这个对象可以说它是类的一个实例(Instance)。实例化一个类可以使用 new 这个关键词。

示例:

const c1 = new Car();

上面这行就是实例化了一下 Car 这个类,也就是基于这个类创建了一个对象,我们把这个对象交给了 c1,可以说 c1 就是 Car 这个类的一个实例。

创建的实例(对象)里面会包含类里的属性与方法,但是 Car 现在是个空白的类,下面我们给它添加点属性还有方法。

属性

属性(Property)就是类里的一些数据,也可以叫做字段(Field)或者成员(Member)。

写法:

class ClassName {
  propertyName;
}

示例:

class Car {
  engine;
}

在上面这个 Car 类里面有个属性叫 engine,现在基于这个类创建的对象里,天生就会拥有 engine 这个属性了。

方法

方法(Method)是类里面定义的一些行为,也就是可以做的事情,其它就是一些函数。

写法:

class ClassName {
  methodName() {}
}

示例:

class Car {
  engine;

  drive() {
    console.log('呜~呜~~~');
  }
}

上面这个 Car 里面有个 engine 属性,还有个 drive() 方法,基于这个类创建的对象里面天生就会拥有这个属性与方法。

const c1 = new Car();

c1.drive();

构造方法

类里有个特别的方法叫构造方法(Constructor),在实例化类,也就是基于类去创建对象的时候,会自动执行这个方法。你可以在这个构造方法里安排一些事情。

写法:

class ClassName {
  constructor() {}
}

示例:

class Car {
  engine;

  constructor() {
    console.log('一辆崭新的汽车!');
  }

  drive() {
    console.log('呜~呜~~~');
  }
}

在上面这个类里使用了构造方法,现在实例化这个类的时候就会执行在这个构造方法安排的事情,这里就是在控制台上输出一行文字:一辆崭新的汽车!

this

在类里面用 this 可以表示基于这个类创建的对象本身。

示例:

class Car {
  engine;

  constructor(engine) {
    this.engine = engine;

    console.log('一辆崭新的汽车!');
  }

  drive() {
    console.log('呜~呜~~~');
  }
}

在上面这个类的构造方法里,用了一下 this 关键词,this.engine 表示的是对象里的 engine 属性。这里设置了一下这个属性的值,让它等于构造方法里的 engine 参数的值。这样如果基于这个类创建对象的时候,可以设置 engine 参数的值,在构造方法里,会把这个参数的值交给 engine 属性。

const c1 = new Car('V8');
const c2 = new Car('V12');

基于 Car 这个类创建了两个对象:c1 与 c2。因为现在 Car 这个类的构造方法里支持一个参数,所以在创建对象的时候我们可以设置一下这个参数的值,这个参数的值会交给对象的 engine 属性。所以在访问 c1.engine 的时候,得到的应该就是 V8。访问 c2.engine 的时候,得到的会是 V12

继承

一个类可以继承(Extends)其它的类,这样这个类里面就会拥有它继承的类里面的东西了。继承可以使用 extends 关键词。

写法:

class Class3 extends Class1 {}

示例:

class Car {
  drive() {
    console.log('呜~呜~~~');
  }
}

上面定义了一个叫 Car 的类,里面有个 drive() 方法。下面可以再去定义一个类,让这个类继承一下 Car 这个类。

class PickupTruck extends Car {}

PickupTruck(皮卡)这个类继承了 Car 这个类,所以它里面就会拥有 Car 这个类里的东西了,比如 drive() 这个方法。

const p1 = new PickupTruck();

p1.drive();

天生就有的东西

在 JavaScript 语言里,有一些天生就有的东西,比如 consoleJSON 对象,parseInt() 函数等等。之前我们用过 console 对象上的 log() 方法在控制台上输出了一些内容,后面我们还要介绍使用 JSON 这个对象,处理 JSON 格式的数据,用 parseInt() 函数把数据转换成数字类型的值。

字符串,数字,数组,对象等等这些东西,它们天生会拥有一些属性还有方法。比如字符串与数组的上面都会有一个 length 属性,它的值就是字符的个数或者数组项目的个数,数组上面有很多方法可以处理数组,可以添加,删除,查找,排序,截取数据项目。

结语

JavaScript 语言的写法还有很多,没有必要一下子都学完,上面这些就足以让你起步工作了,剩下的可以留到实际的工作中学习,这样效果会更好一些。我们也没有必要把它们都记住,你只需要先知道有这些个东西,知道它们的作用是什么就够了,具体的写法随时都可以查资料复习,以后写的多了也就记住了。MDN(Mozilla Developer Network)这个网站上提供了非常详细的文档,遇到语法问题可以到这个网站上搜索一下。

在后面我们还会介绍一些写法,不过要在真正需要用到的时候才会去学习它们。

微信好友

用微信扫描二维码,
加我好友。

微信公众号

用微信扫描二维码,
订阅宁皓网公众号。

240746680

用 QQ 扫描二维码,
加入宁皓网 QQ 群。

统计

15260
分钟
0
你学会了
0%
完成

社会化网络

关于

微信订阅号

扫描微信二维码关注宁皓网,每天进步一点