本章会简要地列举一下到目前为止我们已经学过的 JavaScript 特性。酒香初上,我们先微醺一下。
代码结构
语句之间使用分号分隔:
alert('Hello'); alert('World');
通常换行也被看做是一个分隔符,所以下面这样写也是可以的:通常也被看做是一个分隔符,所以下面这样写也是可以的:
alert('Hello')
alert('World')
这要归功于 JavaScript 中的“自动分号插入”机制。但有时也有问题:
alert('这条信息关闭后,就会报错的')
[1, 2].forEach(alert)
多数代码风格指南都会建议在每个语句后面加上分号,避免可能出现的报错。
代码块 {...}
后面就不需要加分号了。比如下面列举的函数声明和 for
循环例子:( 或这个像循环这样的语法结构),分号是不需要的:
function f() {
} // 这里不需要加分号
for(;;) {
} // 这里也无需加分号
如果我们在哪个地方多写了个分号也不会报错的,因为它会被忽略。
更多参见:《代码结构》。
严格模式
为了能够使用现代 JavaScript 的所有特性,我们最好在脚本顶部使用 "use strict"
声明:
"use strict";
...
这条声明(或叫“指令”)必须写在脚本代码的顶部,也可以写在函数的顶部。
就是不写 "use strict"
,代码也能正常运行,但却是以旧的、“兼容的”方式运行的。我们通常更喜欢现代的行为。
像这门语言最近引入的一些特性(比如我们后面要学的类)默认就隐式地启用了严格模式。
译注:这里所谓的“现代 JavaScript ”,是指代码在执行时,不是以旧的、“兼容的”方式运行。这能避免早期过于宽松的代码语法带来的难以理解和调试的困扰。
更多参见:《严格模式》。
变量
声明变量可以使用:
let
const
(表示声明常量,用此声明的变量初始化时必须赋值,之后也不能改变)var
(旧的声明变量的方式,后面会讲到)
变量名由:
字母和数字组成,但首字符不能是数字。
字符
$
和_
跟字母一样,也可以使用。非拉丁字母和象形文字也是合法的字母,但通常不会使用。
变量的类型是动态的,也就是说一个变量可以储存任意类型的值:
let x = 5;
x = 'John';
一共有七种数据类型:
number
:包括双精度浮点数和整数,boolean
:true/false,string
:字符串,null
:这个类型里只有一个值null
,代表“空”或者“不存在”,undefined
:这个类型里也只有一个值undefined
,代表“没有赋值”,object
和symbol
:分别复杂数据结构和唯一标识符,我们还没有学到。
typeof
操作符返回一个值的类型,但有两个:
typeof null == "object" // 这是 JavaScript 的一个 bug
typeof function(){} == "function" // 函数返回的不是 "object",而是 "function"
交互
我们的工作环境是浏览器,这个宿主环境为我们提供了几个具备简单 UI 界面的交互函数:
弹出一个包含输入框的弹框,输入框上面显示的是你的问题,输入框里的内容会作为返回值返回。如果用户点击了“取消”,那么返回值为 null
。
弹出一个确认框,框内显示的内容是你调用时使用的 message
。如果用户点击了“确认”,返回值是 true
;点击“取消”的话,返回值是 false
。
弹出一个消息框,框内显示的内容是你调用时使用的 message
。点击“确定”即可关闭弹窗。
所有这些交互函数都是以模态窗的形式出现的,当这些窗口弹出时,会暂停当前代码的执行,除非用户应答,否则操作不了页面的其他部分。
例如:
let userName = prompt("Your name?", "Alice");
let isTeaWanted = confirm("Do you want some tea?");
alert( "Visitor: " + userName ); // Alice
alert( "Tea wanted: " + isTeaWanted ); // true
更多参见:《交互函数:alert、prompt 和 confirm》。
运算符
JavaScript 支持下列这些运算符:
算术
除了常规的 +
、-
、*
、/
,还有取模运算符 %
和求幂运算符 **
。
两元加运算符可以用来连接字符串。如果其中一个操作数是字符串,那么另一个会被转为字符串:
alert( '1' + 2 ); // '12' 是个字符串
alert( 1 + '2' ); // '12' 是个字符串
赋值
举两个例子:简单赋值语句:a = b
,以及复合赋值语句:a *= 2
。
位
位运算符处理最底层的、32位整数级别上的运算。以后用到时候,查下文档就行了。
条件
这是唯一一个包含三个参数的运算符:cond ? resultA : resultB
。如果 cond
是真值,就返回 resultA
,否则返回 resultB
。
逻辑
逻辑运算符与 &&
和或 ||
都属于短路求值,返回值就是运算终止时停留在的那个操作数(就是说返回值不一定是 true
/false
)。逻辑非 !
运算符会将操作数转换为布尔,然后取反,最后返回。
比较
当相等运算符 ==
两边的值是不同类型的时,会转换为数值进行比较(null
和 undefined
除外,它们彼此相等,与其他值比较是都不等)。因此,下列的比较结果返回 true
:
alert( 0 == false ); // true
alert( 0 == '' ); // true
其他的比较运算符也遵循这一转换规则。
值得注意的是,严格相等运算符 ===
不发生类型转换。对于它来说,不同类型就意味着不相等。
null
和 undefined
稍微特殊点:用 ==
比较它们时,得到的是 true
,但与其他值比较就是 false
。
当大于/小于运算符两边都是字符串时,使用的是另一个比较规则:会逐个字符比较字符串,比较的实际是字符底层的 Unicode 码点的大小;其他情况,都会将运算数转换成数字后再比较。
其他的
除此之外,还有像逗号运算符在内的其他的运算符。
循环
- 我们讲了三种循环语法。
// 1. while 循环
while (condition) {
...
}
// 2. do { ... } while 循环
do {
...
} while (condition);
// 3. for 循环
for(let i = 0; i < 10; i++) {
...
}
在
for(let ...)
中声明的变量,只在循环体内才可以访问,但是我们也可以忽略 let 然后重用已经存在的变量。break
/continue
关键字用来退出循环/忽略当前迭代、进入下一次迭代。使用label
关键字则可以实现嵌套循环时,跨循环 break、continue 的功能。
更多参见:《while、for 循环》。
后面我们还会学到其他的循环语法,可以用来循环对象。
switch 语句
switch
语句可以用来替换多分支 if
判断。内部呢,是使用严格相等运算符 ===
来做比较的。
例如:
let age = prompt('你多大啦?', 18);
switch (age) {
case 18:
// prompt 返回的结果字符串, 不是数值,所以不会执行这个分支判断
alert('不会执行这个分支判断');
case '18':
alert('而会执行这个分支判断');
break;
default:
alert('如果 `age` 不是数值 18 也不是字符串 "18",就会执行这个分支判断');
}
更多参见:《switch 语句》。
函数
我们介绍了三种创建函数的方式:
- 函数声明:在主代码流(main code flow)中出现的函数
function sum(a, b) {
let result = a + b;
return result;
}
- 函数表达式:在表达式中出现的函数
let sum = function(a, b) {
let result = a + b;
return result;
}
- 箭头函数
// 作为表达式右值
let sum = (a, b) => a + b;
// 如果函数里有多行语句,就要使用花括号 { ... }, 还要有 return:
let sum = (a, b) => {
// ...
return a + b;
}
// 没有参数的情况
let sayHi = () => alert("Hello");
// 有一个参数
let double = n => n * 2;
函数可以有局部变量:在函数里声明,也只能在函数里才能访问到。
参数可以有默认值:
function sum(a=1, b=2) {...}
。函数总是有返回值。如果函数里没有写
return
,默认返回值是undefined
。
更多参见:《函数》、《函数表达式和箭头函数》。
还有更多
这里只是简要地列举了到目前为止我们已经学过的 JavaScript 特性,这些都是基础。以后,我们还会学到更多、更高级的 JavaScript 特性。
(完)