JavaScript 基础(五):语句

234 阅读3分钟

if 语句

语法:

if (condition) {
    statement1
} else {
    statement2
}
  • condition:表达式,求值结果会被转换为布尔值,为 true 执行语句 statement1,为 false 执行语句 statement2。
  • 可连续使用多个 if 语句。
if (i > 25) { 
    console.log("Greater than 25."); 
} else if (i < 0) { 
    console.log("Less than 0."); 
} else { 
    console.log("Between 0 and 25, inclusive."); 
}

最佳实践是使用语句块,即使只有一行代码要执行也是如此。这是因为语句块可以避免对什么条件下执行什么产生困惑。

while 语句

while 语句是一种先测试循环语句,即先检测退出条件,再执行循环体内的代码。因此,while 循环体内的代码有可能不会执行

语法:

while(expression) {
    statement
}
  • condition:表达式,求值结果会被转换为布尔值,为 true 执行语句 statement。

例子:

let i = 0; 
while (i < 10) { 
    i += 2; 
} 

在这个例子中,变量 i 从 0 开始,每次循环递增 2。只要 i 小于 10,循环就会继续。

无限循环:while (true) {...}

do...while 语句

do...while 语句是一种后测试循环语句,即先执行循环体中的代码后,才会对退出条件进行求值。换句话说,循环体内的代码至少执行一次

语法:

do { 
    statement 
} while (expression); 

例子:

let i = 0; 
do { 
    i += 2; 
} while (i < 10); 

在这个例子中,只要 i 小于 10,循环就会重复执行。i 从 0 开始,每次循环递增 2。

for 语句

for 语句也是先测试语句,只不过增加了进入循环之前的初始化代码,以及循环执行后要执行的表达式

语法:

for (initialization; expression; postLoopExpression){
statement
}
  • initialization:初始化代码
  • expression:退出条件求值表达式
  • postLoopExpression:循环执行后要执行的表达式
let count = 10; 
for (let i = 0; i < count; i++) { 
    console.log(i); 
} 

for 循环的初始化代码中,其实是可以不使用变量声明关键字的。不过,初始化定义的迭代器变量在循环执行完成后几乎不可能再用到了。因此,最清晰的写法是使用 let 声明迭代器变量,这样就可以将这个变量的作用域限定在循环中

初始化、条件表达式和循环后表达式都不是必需的。因此,下面这种写法可以创建一个无穷循环

for (;;) { // 无穷循环
 doSomething(); 
} 

请注意 for 的两个 ; 必须存在,否则会出现语法错误。

for...in 语句

for...in 语句是一种 严格的迭代语句用于枚举对象中的 非符号键 属性

语法: for (property in expression) statement

  • property:局部变量,用于保存键名
  • expression:对象(对象为 nullundefined,则不执行循环体
for (const propName in window) { 
    document.write(propName); 
} 

这个例子使用 for...in 循环显示了 BOM 对象 window 的所有属性。每次执行循环,都会给变量 propName 赋予一个 window 对象的属性作为值,直到 window 的所有属性都被枚举一遍。

for 循环一样,这里控制语句中的 const 也不是必需的。但为了确保这个局部变量不被修改,推荐使用 const

ECMAScript 中对象的属性是无序的,因此 for...in 语句不能保证返回对象属性的顺序。换句话说,所有可枚举的属性都会返回一次,但返回的顺序可能会因浏览器而异。

for...of 语句

for...of 语句是一种 严格的迭代语句用于遍历 可迭代对象 的元素

语法: for (property of expression) statement

for (const el of [2,4,6,8]) { 
    document.write(el); 
} 

for 循环一样,这里控制语句中的 const 也不是必需的。

for...of 循环会按照可迭代对象的 next() 方法产生值的顺序迭代元素

如果尝试迭代的变量不支持迭代,则 for...of 语句会抛出错误。

标签语句

标签语句用于给语句加标签

语法: label: statement

start: for (let i = 0; i < count; i++) { 
    console.log(i); 
} 

在这个例子中,start 是一个标签,可以在后面通过 breakcontinue 语句引用。标签语句的典型应用场景是嵌套循环。标签是 break/continue 调出嵌套循环以转到外部的唯一方法。

标签并不允许我们调到代码的任意位置。 只有在循环内部才能调用 breakcontinue,并且标签必须位于指令上方的某个位置

break label; // 无法跳转到这个标签

label: for (...)

breakcontinue 语句

  • break:结束当前循环
  • continue:跳过当前循环,执行下一次的循环
// break
let num = 0; 
for (let i = 1; i < 10; i++) { 
    if (i % 5 == 0) { 
        break; 
    } 
    num++; 
} 
console.log(num); // 4。当 i 等于 5 时,break 语句会导致循环退出,num 不递增

// continue
let num = 0; 
for (let i = 1; i < 10; i++) { 
    if (i % 5 == 0) { 
        continue; 
    } 
    num++; 
} 
console.log(num); // 8。num 的值是 8 而不是 9,是因为 continue 语句导致它少递增了一次

breakcontinue 都可以与标签语句一起使用,返回代码中特定的位置。这通常是在嵌套循环中,如下面的例子所示:

let num = 0; 
outermost: 
for (let i = 0; i < 10; i++) { 
    for (let j = 0; j < 10; j++) { 
        if (i == 5 && j == 5) { 
            break outermost; 
        } 
        num++; 
    } 
} 
console.log(num); // 55 

在这个例子中,outermost 标签标识的是第一个 for 语句。正常情况下,每个循环执行 10 次,意味着 num++ 语句会执行 100 次,而循环结束时 console.log 的结果应该是 100。但是,break 语句带来了一个变数,即要退出到的标签。添加标签不仅让 break 退出(使用变量 j 的)内部循环,也会退出(使用变量 i 的)外部循环。当执行到 ij 都等于 5 时,循环停止执行,此时 num 的值是 55。

continue 语句也可以使用标签,如下面的例子所示:

let num = 0; 
outermost: 
for (let i = 0; i < 10; i++) { 
    for (let j = 0; j < 10; j++) { 
        if (i == 5 && j == 5) { 
            continue outermost; 
        } 
        num++; 
    } 
} 
console.log(num); // 95 

这一次,continue 语句会强制循环继续执行,但不是继续执行内部循环,而是继续执行外部循环。当 ij 都等于 5 时,会执行 continue,跳到外部循环继续执行,从而导致内部循环少执行 5 次,结果 num 等于 95。

组合使用标签语句和 breakcontinue 能实现复杂的逻辑,但也容易出错。注意标签要使用描述性强的文本,而嵌套也不要太深

with 语句

with 语句的用途是将代码作用域设置为特定的对象

语法: with (expression) statement;

使用 with 语句的主要场景是针对一个对象反复操作,这时候将代码作用域设置为该对象能提供便 利,如下面的例子所示:

let qs = location.search.substring(1); 
let hostName = location.hostname; 
let url = location.href; 

上面代码中的每一行都用到了 location 对象。如果使用 with 语句,就可以少写一些代码:

with(location) { 
 let qs = search.substring(1); 
 let hostName = hostname; 
 let url = href; 
} 

这里,with 语句用于连接 location 对象。这意味着在这个语句内部,每个变量首先会被认为是一个局部变量。如果没有找到该局部变量,则会搜索 location 对象,看它是否有一个同名的属性。如果有,则该变量会被求值为 location 对象的属性。

严格模式不允许使用 with 语句,否则会抛出错误

由于 with 语句影响性能且难于调试其中的代码,通常不推荐在产品代码中使用 with 语句。

switch 语句

switch 语句是与 if 语句紧密相关的一种流控制语句,从其他语言借鉴而来。

switch (expression) { 
    case value1: 
        statement 
        break; 
    case value2: 
        statement 
        break; 
    default: 
        statement 
}        
  • expression:表达式
  • case(条件/分支):如果表达式等于后面的值,则执行下面的 statement 语句。break 关键字会导致代码执行跳出 switch 语句。如果没有 break,则代码会继续匹配下一个条件
  • default 关键字用于在任何条件都没有满足时指定默认执行的语句(相当于 else 语句)。

为避免不必要的条件判断,最好给每个条件后面都加上 break 语句。如果确实需要连续匹配几个条件,那么推荐写个注释表明是故意忽略了 break,如下所示:

switch (i) { 
    case 25: 
    /* 跳过 */ 
    case 35: 
        console.log("25 or 35"); 
        break; 
    case 45: 
        console.log("45"); 
        break; 
    default: 
        console.log("Other"); 
} 

虽然 switch 语句是从其他语言借鉴过来的,但 ECMAScript 为它赋予了一些独有的特性:

  • switch 语句可以用于所有数据类型,因此可以使用字符串甚至对象。
  • 条件的值不需要是常量,也可以是变量或表达式
  • 任何表达式都可以成为 switch/case 的参数
let num = 25; 
switch (true) { 
    case num < 0: 
        console.log("Less than 0."); 
        break; 
    case num >= 0 && num <= 10: 
        console.log("Between 0 and 10."); 
        break; 
    case num > 10 && num <= 20: 
        console.log("Between 10 and 20."); 
        break; 
    default: 
        console.log("More than 20."); 
} 

上面的代码首先在外部定义了变量 num,而传给 switch 语句的参数之所以是 true,就是因为每个条件的表达式都会返回布尔值。条件的表达式分别被求值,直到有表达式返回 true;否则,就会一直跳到 default 语句。

注意:switch 语句在比较每个条件的值时会使用 全等操作符 ,因此不会强制转换数据类型(比如,字符串"10"不等于数值 10)。

return 语句

  • 返回函数的值
  • 函数停止执行并退出
function sum(num1, num2) { 
    return num1 + num2; 
    console.log('该代码不会被执行'); // return 语句后面的代码不会被执行
} 

const result = sum(5, 10);

最佳实践是函数要么返回值,要么不返回值。只在某个条件下返回值的函数会带来麻烦,尤其是调试时。