JS基础(三)

2022-02-15  本文已影响0人  a437e8f87a81

// 循环:while 和 for

// 我们经常需要重复执行一些操作。

// 例如,我们需要将列表中的商品逐个输出,或者运行相同的代码将数字 1 到 10 逐个输出。

// 循环 是一种重复运行同一代码的方法。

// “while” 循环

// while (1) {

//

// }

// 当 condition 为真时,执行循环体的 code。

let i =0;

while (i <3) {// 依次显示 0、1 和 2

    alert(i );

    i++;

}

// 循环体的单次执行叫作 一次迭代。上面示例中的循环进行了三次迭代。

// 如果上述示例中没有 i++,那么循环(理论上)会永远重复执行下去。实际上,浏览器提供了阻止这种循环的方法,我们可以通过终止进程,来停掉服务器端的 JavaScript。

// 任何表达式或变量都可以是循环条件,而不仅仅是比较。在 while 中的循环条件会被计算,计算结果会被转化为布尔值。

// 例如,while (i != 0) 可简写为 while (i):

let i =3;

while (i) {// 当 i 变成 0 时,条件为假,循环终止

    alert(i );

    i--;

}

// “do…while” 循环

do {

// 循环体

}while (condition);

// 循环首先执行循环体,然后检查条件,当条件为真时,重复执行循环体。

let i =0;

do {

alert(i );

    i++;

}while (i <3);

// 这种形式的语法很少使用,除非你希望不管条件是否为真,循环体 至少执行一次。通常我们更倾向于使用另一个形式:while(…) {…}。

// “for” 循环

for (begin; condition; step) {

// ……循环体……

}

for (let i =0; i <3; i++) {// 结果为 0、1、2

    alert(i);

}

// 我们逐个部分分析 for 循环:

// 语句段

// begin  let i = 0  进入循环时执行一次。

// condition  i < 3  在每次循环迭代之前检查,如果为 false,停止循环。

// body(循环体)  alert(i)  条件为真时,重复运行。

// step    i++    在每次循环体迭代后执行。

// 内联变量声明

// 这里“计数”变量 i 是在循环中声明的。这叫做“内联”变量声明。这样的变量只在循环中可见。

for (let i =0; i <3; i++) {

alert(i); // 0, 1, 2

}

alert(i); // 错误,没有这个变量。

// 除了定义一个变量,我们也可以使用现有的变量:

let i =0;

for (i =0; i <3; i++) {// 使用现有的变量

    alert(i); // 0, 1, 2

}

alert(i); //3,可见,因为是在循环之外声明的

// 省略语句段

// for 循环的任何语句段都可以被省略。

// 例如,如果我们在循环开始时不需要做任何事,我们就可以省略 begin 语句段。

// 就像这样:

let i =0; // 我们已经声明了 i 并对它进行了赋值

for (; i <3; i++) {// 不再需要 "begin" 语句段

    alert(i ); // 0, 1, 2

}

// 我们也可以移除 step 语句段:

let i =0;

for (; i <3;) {

alert(i++ );

}

for (;;) {

// 无限循环

}

// 跳出循环

// 通常条件为假时,循环会终止。

// 但我们随时都可以使用 break 指令强制退出。

// 例如,下面这个循环要求用户输入一系列数字,在输入的内容不是数字时“终止”循环。

let sum =0;

while (true) {

let value = +prompt("Enter a number", '');

    if (!value)break; // (*)

    sum += value;

}

alert('Sum: ' +sum );

// 如果用户输入空行或取消输入,在 (*) 行的 break 指令会被激活。它立刻终止循环,将控制权传递给循环后的第一行,即,alert。

// 根据需要,"无限循环 + break" 的组合非常适用于不必在循环开始/结束时检查条件,但需要在中间甚至是主体的多个位置进行条件检查的情况。

// 继续下一次迭代

// continue 指令是 break 的“轻量版”。它不会停掉整个循环。而是停止当前这一次迭代,并强制启动新一轮循环(如果条件允许的话)。

// 如果我们完成了当前的迭代,并且希望继续执行下一次迭代,我们就可以使用它。

// 下面这个循环使用 continue 来只输出奇数:

if (let i =0, i <10, i++) {

if (i %2 ==0)continue;

}

// 对于偶数的 i 值,continue 指令会停止本次循环的继续执行,将控制权传递给下一次 for 循环的迭代(使用下一个数字)。因此 alert 仅被奇数值调用。

// continue 指令利于减少嵌套

// 显示奇数的循环可以像下面这样

for (let i =0; i <10; i++) {

if (i %2) {

alert( i );

    }

}

// 禁止 break/continue 在 ‘?’ 的右边

// break/continue 标签 暂时未用到

// 有时候我们需要从一次从多层嵌套的循环中跳出来。

// 例如,下述代码中我们的循环使用了 i 和 j,从 (0,0) 到 (3,3) 提示坐标 (i, j):

outer:for (let i =0; i <3; i++) {

for (let j =0; j <3; j++) {

let input =prompt(`Value at coords (${i},${j})`, '');

        // 如果是空字符串或被取消,则中断并跳出这两个循环。

        if (!input)break outer; // (*)

// 用得到的值做些事……

    }

}

alert('Done!');

我们学习了三种循环:

// while —— 每次迭代之前都要检查条件。

// do..while —— 每次迭代后都要检查条件。

// for (;;) —— 每次迭代之前都要检查条件,可以使用其他设置。

// 通常使用 while(true) 来构造“无限”循环。这样的循环和其他循环一样,都可以通过 break 指令来终止。

// 如果我们不想在当前迭代中做任何事,并且想要转移至下一次迭代,那么可以使用 continue 指令。

// break/continue 支持循环前的标签。标签是 break/continue 跳出嵌套循环以转到外部的唯一方法。

// 大于 1 且不能被除了 1 和它本身以外的任何数整除的整数叫做素数。

// 换句话说,n > 1 且不能被 1 和 n 以外的任何数整除的整数,被称为素数。

// 例如,5 是素数,因为它不能被 2、3 和 4 整除,会产生余数。

// 写一个可以输出 2 到 n 之间的所有素数的代码。

// 当 n = 10,结果输出 2、3、5、7。

// P.S. 代码应适用于任何 n,而不是对任何固定值进行硬性调整。

// 对于间隔中的每个 i {

//    检查在 1~i 之间,是否有 i 的除数

//    如果有 => 这个 i 不是素数

//    如果没有 => 这个 i 是素数,输出出来

// }

// let n = 10;

//

// nextPrime:

//    for (let i = 2; i <= n; i++) { // 对每个自然数 i

//

//        for (let j = 2; j < i; j++) { // 寻找一个除数……

//            if (i % j == 0) continue nextPrime; // 不是素数,则继续检查下一个

//        }

//

//        alert( i ); // 输出素数

//    }

// "switch" 语句

// switch 语句可以替代多个 if 判断。

let x ="xxx"

switch (x) {

case "xxx":

alert(x)

break

    case "xxx":

alert(x)

break

    default:

alert(x)

}

//分组

let a =3;

switch (a) {

case 4:

alert('Right!');

break;

    case 3:// (*) 下面这两个 case 被分在一组

    case 5:

alert('Wrong!');

        alert("Why don't you take a math class?");

break;

    default:

alert('The result is strange. Really.');

}

// 类型很关键

// 强调一下,这里的相等是严格相等。被比较的值必须是相同的类型才能进行匹配。

// 函数

function showMessage() {

alert('xxxxx')

}

showMessage()

function showMessageWtih(par1,par2) {

alert(par1 + par2)

}

showMessageWtih("x","sss")

// 全局变量

// 任何函数之外声明的变量,例如上述代码中的外部变量 userName,都被称为 全局 变量。

// 全局变量在任意函数中都是可见的(除非被局部变量遮蔽)。

// 减少全局变量的使用是一种很好的做法。现代的代码有很少甚至没有全局变量。大多数变量存在于它们的函数中。但是有时候,全局变量能够用于存储项目级别的数据。

// 参数

// 我们可以通过参数将任意数据传递给函数。

function showMessage(from, text) {// 参数:from 和 text

    alert(from +': ' + text);

}

showMessage('Ann', 'Hello!'); // Ann: Hello! (*)

showMessage('Ann', "What's up?"); // Ann: What's up? (**)

// 换一种方式,我们把这些术语搞清楚:

// 参数(parameter)是函数声明中括号内列出的变量(它是函数声明时的术语)。

// 参数(argument)是调用函数时传递给函数的值(它是函数调用时的术语)。

// 默认值

// 如果一个函数被调用,但有参数(argument)未被提供,那么相应的值就会变成 undefined。

// 例如,之前提到的函数 showMessage(from, text) 可以只使用一个参数(argument)调用:

// showMessage("Ann");

// 那不是错误,这样调用将输出 "*Ann*: undefined"。因为参数 text 的值未被传递,所以变成了 undefined。

// 我们可以使用 = 为函数声明中的参数指定所谓的“默认”(如果对应参数的值未被传递则使用)值:

// function showMessage(from, text = "no text given") {

//    alert( from + ": " + text );

// }

// showMessage("Ann");

// 现在如果 text 参数未被传递,它将会得到值 "no text given"。

// 这里 "no text given" 是一个字符串,但它可以是更复杂的表达式,并且只会在缺少参数时才会被计算和分配。所以,这也是可能的:

function showMessage(from, text = anotherFunction()) {

// anotherFunction() 仅在没有给定 text 时执行

// 其运行结果将成为 text 的值

}

// 在 JavaScript 中,每次函数在没带个别参数的情况下被调用,默认参数会被计算出来。

// 在上面的例子中,如果传递了参数 text,那么 anotherFunction() 就不会被调用。

// 如果没传递参数 text,那么 anotherFunction() 就会被调用。

// 后备的默认参数

// 有些时候,将参数默认值的设置放在函数执行(相较更后期)而不是函数声明时,也行得通。

// 我们可以通过将参数与 undefined 进行比较,来检查该参数是否在函数执行期间被传递进来:

function showMessage(text) {

// ...

    if (text ===undefined) {// 如果参数未被传递进来

        text ='empty message';

    }

alert(text);

}

showMessage(); // empty message

function showCount(count) {

// 如果 count 为 undefined 或 null,则提示 "unknown"

    alert(count ??"unknown");

}

showCount(0); // 0

showCount(null); // unknown

showCount(); // unknown

// 返回值

function sum(a,b) {

return a + b

}

alert(sum(1,2))

// 指令 return 可以在函数的任意位置。当执行到达时,函数停止,并将值返回给调用代码(分配给上述代码中的 result)。

function checkAge(age) {

if (age >=18) {

return true;

    }else {

return confirm('Got a permission from the parents?');

    }

}

let age =prompt('How old are you?', 18);

if (checkAge(age) ) {

alert('Access granted' );

}else {

alert('Access denied' );

}

function showMovie(age) {

if ( !checkAge(age) ) {

return;

    }

alert("Showing you the movie" ); // (*)

// ...

}

// 函数命名

// 函数就是行为(action)。所以它们的名字通常是动词。它应该简短且尽可能准确地描述函数的作用。这样读代码的人就能清楚地知道这个函数的功能。

// 一种普遍的做法是用动词前缀来开始一个函数,这个前缀模糊地描述了这个行为。团队内部必须就前缀的含义达成一致。

// 例如,以 "show" 开头的函数通常会显示某些内容。

// 函数以 XX 开始……

// "get…" —— 返回一个值,

// "calc…" —— 计算某些内容,

// "create…" —— 创建某些内容,

// "check…" —— 检查某些内容并返回 boolean 值,等。

// showMessage(..)    // 显示信息

// getAge(..)          // 返回 age(gets it somehow)

// calcSum(..)        // 计算求和并返回结果

// createForm(..)      // 创建表单(通常会返回它)

// checkPermission(..) // 检查权限并返回 true/false

// 作为参数传递给函数的值,会被复制到函数的局部变量。

// 函数可以访问外部变量。但它只能从内到外起作用。函数外部的代码看不到函数内的局部变量。

// 函数可以返回值。如果没有返回值,则其返回的结果是 undefined。

// 为了使代码简洁易懂,建议在函数中主要使用局部变量和参数,而不是外部变量。

// 与不获取参数但将修改外部变量作为副作用的函数相比,获取参数、使用参数并返回结果的函数更容易理解。

// 函数命名:

// 函数名应该清楚地描述函数的功能。当我们在代码中看到一个函数调用时,一个好的函数名能够让我们马上知道这个函数的功能是什么,会返回什么。

// 一个函数是一个行为,所以函数名通常是动词。

// 目前有许多优秀的函数名前缀,如 create…、show…、get…、check… 等等。使用它们来提示函数的作用吧。

// 函数是脚本的主要构建块。现在我们已经介绍了基本知识,现在我们就可以开始创建和使用函数了。但这只是学习和使用函数的开始。我们将继续学习更多函数的相关知识,更深入地研究它们的先进特征。

function checkAge(age) {

return (age >18) ?true :confirm('Did parents allow you?');

}

使用或运算符 ||(最短的变体):

function checkAge(age) {

return (age >18) ||confirm('Did parents allow you?');

}

function pow(x, n) {

let result = x;

    for (let i =1; i < n; i++) {

result *= x;

    }

return result;

}

let x =prompt("x?", '');

let n =prompt("n?", '');

if (n <1) {

alert(`Power ${n} is not supported, use a positive integer`);

}else {

alert(pow(x, n) );

}

上一篇下一篇

猜你喜欢

热点阅读