# YDKJS-编程
总结深入学习和实践编程所需要的知识,此外还有许多其他介绍编程的优秀资源,这些资源可以帮助你更深入地探索这些主题。
# 代码
程序常被称为源码或代码,它是一组特定的指令,用来指示计算机要执行哪些任务。虽然对 JavaScript 来说可以直接在浏览器的开发者终端中输入代码,但代码通常会被保存在文本文件中。
指令的格式和组合规则被称为计算机语言,有时也被称为语法,这非常类似于英语中告诉你如何拼写单词以及如何使用单词和标点符号来构造有效的句子。
# 语句
在计算机语言中,执行特定任务的一组单词、数字和运算符被称为语句。在 JavaScript 中,一条语句可能如下所示:
a = b * 2
其中的字符 a
和 b
称为变量,它们就好比是可以存放东西的小盒子。在程序中,变量保存程序要使用的值(比如数字 42)。你可以将它们想象成值本身的替代符。
相比之下,2 本身就是一个值,称为字面值,因为它独立存在而没有保存在变量之中。其中的字符 =
和 *
是运算符,它们对值和变量执行动作,如赋值和进行乘法运算。
JavaScript 的多数语句都是以分号( ;)结尾的。
程序就是多个这样语句的集合,它们合起来描述了程序要执行的所有步骤。
# 表达式
语句由一个或多个表达式组成。一个表达式是对一个变量或值的引用,或者是一组值和变量与运算符的组合。
举例来说,a = b * 2;
这个语句中有四个表达式:
- 2 是一个字面值表达式。
b
是一个变量表达式,表示获取它的当前值。b * 2
是一个算术表达式,表示进行乘法运算。a = b * 2
是一个赋值表达式,意思是将表达式b * 2
的结果赋值给变量a
。
一个独立的表达式也可以称为表达式语句,如下所示:
b * 2
这种表达式语句不是很常用,或者说不是很有用,因为它通常不会对程序的运行起到任何作用,它只是取得 b
的值并乘以 2,但是却没有对结果有任何影响。
更常用的表达式语句是调用表达式语句,因为整个语句本身就是一个函数调用表达式:
alert(a)
# 执行程序
这些编程语句的集合是如何通知计算机来执行任务的呢?程序需要被执行,我们也将这一过程称为运行程序。
a = b * 2
这样的语句便于开发者读写,但实际上计算机并不能直接理解这种形式。因此,需要通过计算机上一个专门的工具(解释器或编译器)将你编写的代码翻译成计算机可以理解的命令。
对某些计算机语言来说,在程序被执行时,对命令的翻译通常是自上而下逐行执行的,这通常被称为代码解释。
对另外一些语言来说,这种翻译是预先进行的,被称为代码编译,这样一来,当执行程序时,实际上运行的是已经编译好的、可以执行的计算机指令。
基本上可以说 JavaScript 是解释型的,因为每次执行 JavaScript 源码时都需要进行处理。但这么说并不完全精确。JavaScript 引擎实际上是动态编译程序,然后立即执行编译后的代码。
# 实践
我们来熟悉一下在终端中运行代码的流程。首先,建议你在浏览器中打开一个空白的标签页。我更喜欢在地址栏中输入 about:blank
来实现这一点。然后,确保你的开发者终端是开启状态。
现在,输入如下代码,并观察代码的执行:
a = 21
b = a * 2
console.log(b)
在 Chrome 浏览器的终端中输入前面的代码将会产生如下所示的输出:
# 输出
在前面的代码片段中,我们使用了 console.log(..)
。现在我们来简单了解一下这行代码做了些什么。
可能你已经猜到了,这就是我们在开发者终端打印文本(即向用户输出)的方法。我们应该对这个语句的两点解释一下。
首先,log( b )
这一部分是一个函数调用。我们将变量 b
传给这个函数,请求它将 b
的值打印到终端中。
其次,console.
这一部分是 log(..)
函数所在的对象引用。
创建可见输出的另外一个方法是运行 alert(..)
语句。如下所示:
alert(b)
如果运行这个语句,那么你就会发现输出并没有打印到终端中,而是弹出一个“OK”对话框,变量 b
的内容会呈现在对话框中。然而,在终端中学习和运行程序时,使用 console.log(..)
通常比使用 alert(..)
更加方便,因为这样无需与浏览器界面交互就可以一次输出多个变量。
我们在本部分中使用 console.log(..)
作为输出方法。
# 输入
最常用的方法是,通过 HTML 页面向用户显示表单元素(如文本框)用于输入,然后通过 JavaScript 将这些值读取到程序变量中。
还有另一种更为简单的获取输入的方法,用于简单的学习和展示,这也是我们将会使用的方法,即 prompt(..)
函数:
age = prompt('Please tell me your age:')
console.log(age)
输入文本并点击“OK”后,你就可以看到输入的值会保存到变量 age
中,接着通过 console.log(..)
输出。
# 运算符
使用运算符,我们可以对变量和值执行操作。我们已经在前文中看到了 =
和 *
这两个 JavaScrit 运算符。
等号运算符 =
用于赋值——我们先计算 =
右边(源值)的值,然后将它存入左边(目标变量)指定的变量中。
a = 2
b = a + 1
在上述示例中,我们将值 2 赋给变量 a
。然后,我们取得变量 a
的值(仍然是 2),加上 1,得到结果 3,再将这个值保存在变量 b
中。
虽然 var
严格意义上说并不是一个运算符,但每个程序都会用到这个关键词,因为它是声明(也就是创建)变量的基本方法。
在使用变量前总是应该先声明变量。一个变量在每个作用域中只需要声明一次;声明之后可以按照需要多次使用。
# 值与类型
在编程术语中,对值的不同表示方法称为类型。JavaScript 为以下这些基本值提供了内置类型。
- 在计算时,你需要的是一个数字(number)。
- 在屏幕上打印一个值时,你需要的是一个字符串(string,一个或多个字符、单词或句子)。
- 在程序中作出决策时,你需要的是一个布尔值(boolean,true 或者 false)。
直接包含在源码中的值被称为字面值。字符串字面值由双引号("...")或单引号('…')围住,二者的唯一区别只是风格不同。数字和布尔型字面值可以直接表示(如 42、true 等)。
除了字符串/数字/布尔值类型,编程语言通常还会提供数组、对象、函数等。
如果需要在屏幕上打印出一个数字,那么就需要将这个值转化为字符串,在 JavaScript 中,这种转化称为“类型转换”。
# 代码注释
另一个非常重要的部分是代码注释。这是程序中的文本,将其插入程序只是为了向人类解释说明代码的执行。解释器/编译器会忽略这些注释。
有关如何编写注释良好的代码有很多种观点;我们确实无法定义绝对的普遍标准。但是以下这些观察结论和指导原则是很有用的:
- 没有注释的代码不是最优的。
- 过多注释(比如每行一个)可能是拙劣代码的征兆。
- 代码应该解释为什么,而非是什么。如果编写的代码特别容易令人迷惑的话,那么注释也可以解释一下实现原理。
JavaScript 中的注释有两种类型:单行注释和多行注释。
// 这是一个单行注释
/* 而这是
一个多行
注释。
*/
如果想要将注释放到单个语句上方或者一行的末尾,那么可以使用单行注释 //
。这一行中位于 //
之后直到行尾的所有内容都会被当作注释(因此会被编译器忽略)。单行注释的内容没有限制。
# 变量
大多数的实用程序都需要跟踪值的变化,因为程序在执行任务时会对值进行各种操作,值会不断发生变化。
在程序中实现这一点的最简单方法是将值赋给一个符号容器,这个符号容器称为变量,使用这个名字是因为这个容器中的值是可以变化的。
在某些编程语言中,你需要声明一个变量(容器)用于存放指定类型的值(如数字或字符串)。通过避免不想要的值转换,人们认为这种静态类型(也称为类型强制)提高了程序的正确性。
其他语言强调的是值的类型而不是变量的类型。弱类型(也称为动态类型)允许一个变量在任意时刻存放任意类型的值。这种方式允许一个变量在程序的逻辑流中的任意时刻代表任意类型的值,人们认为这样可以提高程序的灵活性。
JavaScript 采用了后一种机制——动态类型,这也就是说,变量可以持有任意类型值而不存在类型强制。
var amount = 99.99
amount = amount * 2
变量的主要用途:管理程序状态。换句话说,状态跟踪了值随着程序运行的变化。
变量的另一个常见用法是集中设置值。更常见的说法是常量,即声明一个变量,赋予一个特定值,然后这个值在程序执行过程中保持不变。
在 JavaScript 中作为常量的变量用大写表示,多个单词之间用下划线 _
分隔。
const TAX_RATE = 0.08
# 块
我们常常需要将在代码中的一系列语句组织到一起,这些语句通常被称为块。 在 JavaScript 中,使用一对大括号 { .. }
在一个或多个语句外来表示块。
通常来说,块会与其他某个控制语句组合在一起,比如 if
语句或循环:
var amount = 99.99
// amount是否足够大呢?
if (amount > 10) {
// <-- 块与if组合
amount = amount * 2
console.log(amount) // 199.98
}
块语句不需要以分号(;)结尾。
# 条件判断
程序中有很多种方法可以用于表示条件判断(也就是决策)。
最常用的是 if
语句。本质上就是在表达“如果这个条件是真的,那么 ...”。你还可以提供一个用于 if
条件不为真时的选择,我们将其称为 else
语句。
const ACCESSORY_PRICE = 9.99
var bank_balance = 302.13
var amount = 99.99
amount = amount * 2
// 是否可以提供额外的购买?
if (amount < bank_balance) {
console.log("I'll take the accessory!")
amount = amount + ACCESSORY_PRICE
}
// 否则
else {
console.log('No, thanks.')
}
if
语句需要布尔型的值,如果传递的值是非布尔型的,那么就会发生类型转换。
除 if
之外,还有其他形式的条件判断。比如,switch
语句可以用作一组 if..else
语句的简写。循环通过一个条件判断来确定是继续还是停止。
# 循环
重复一系列动作,直到不满足某个条件,换句话说,重复只发生在满足条件的情况下,这就是程序循环的工作;循环有多种形式,但都满足基本的行为特性。
循环包括测试条件以及一个块(通常就是 { .. })。循环块的每次执行被称为一个迭代。
比如,while
循环和 do..while
循环形式展示了重复一个语句块直到一个条件判断求值不再为真这个概念:
while (numOfCustomers > 0) {
console.log('How may I help you?')
numOfCustomers = numOfCustomers - 1
}
// 对比
do {
console.log('How may I help you?')
numOfCustomers = numOfCustomers - 1
} while (numOfCustomers > 0)
这些循环之间的唯一实际区别是,条件判断在第一次迭代执行前(while)检查还是在第一次迭代后(do..while)检查。
虽然使用 while
(或者 do..while)循环也可以手动完成任务,但还有一个专门为此设计的语法形式,我们将其称为 for
循环:
for (var i = 0; i <= 9; i = i + 1) {
console.log(i)
}
// 0 1 2 3 4 5 6 7 8 9
我们可以通过 JavaScript 的 break
语句来结束循环。
# 函数
你的程序也几乎总是需要将代码的任务分割成可复用的片段,而不是一直重复编码。实现这一点的方法就是定义一个函数。
通常来说,函数是可以通过名字被“调用”的已命名代码段,每次调用,其中的代码就会运行。也可以接受参数或返回一个值。
function printAmount(amt) {
console.log(amt.toFixed(2))
}
function formatAmount() {
return '$' + amount.toFixed(2)
}
var amount = 99.99
printAmount(amount * 2) // "199.98"
amount = formatAmount()
console.log(amount) // "$99.99"
多数时候,你会在计划多次调用的代码上使用函数,但只是将相关的代码组织到一起成为命名集合也是很有用的,即使只准备调用一次。
在 JavaScript 中,每个函数都有自己的作用域。作用域基本上是变量的一个集合以及如何通过名称访问这些变量的规则。只有函数内部的代码才能访问这个函数作用域中的变量。
同一个作用域内的变量名是唯一的,所以不能有两个变量 a
一个接一个地放在一起。但是,同一个变量名 a
可以出现在不同的作用域中:
function one() {
// 这个a只属于one()函数
var a = 1
console.log(a)
}
function two() {
// 这个a只属于two()函数
var a = 2
console.log(a)
}
one() // 1
two() // 2
此外,作用域是可以彼此嵌套的,就好像生日聚会上的小丑可以在一个气球内部吹起另一个气球那样。如果一个作用域嵌套在另外一个作用域内,那么内层作用域中的代码可以访问这两个作用域中的变量。
词法作用域的规则表明,一个作用域内的代码可以访问这个作用域内以及任何包围在它之外的作用域中的变量。
# 实践?嗯
学习编程的最好方法就是编写代码。
← YDKJS-高级异步模式 代码优化 →