龙空技术网

第13节 流程控制语句-循环控制-零点程序员-王唯

零点程序员 114

前言:

现在同学们对“js中循环语句关键字是”大约比较关怀,我们都想要分析一些“js中循环语句关键字是”的相关文章。那么小编也在网络上汇集了一些关于“js中循环语句关键字是””的相关内容,希望看官们能喜欢,大家快快来了解一下吧!

循环语句:

当一系列语句需要反复执行,需要使用循环语句(loop);

JavaScript的循环语句包括:for、while ;

细分为四种、 for、for…in、while 、 do…while

while语句:

while循环属于前测试循环语句,在执行循环体前测试一个条件,如果条件成立则进入循环体,否则跳到循环后的第一条语句。因此,如果条件一开始就不成立,其永远不会被执行;

语法:

while(expression)

{

statement;

}

while循环

说明:首先会解析expression值,如果是假值,则跳过循环体;如果是真值,则执行循环体,然后再次计算expression值,这种循环会一直继续下去,直到espression的值为假值为止;或者说,只要expression是真值则一直循环执行statement;因此,有可能会创建一个死循环。

var count = 0;while(count < 10){    console.log(count);    count++;}

说明:count初始始值是0,在循环执行过程中,它的值每次递增1,当循环了10次,表达式的值变成了false,此时while就会结束。

又如:

var i=1,sum = 0;while(i <= 100){    sum += i;    i++;};console.log("1到100之各为:" + sum);

在实际场景中,循环都会有一个像count这样的计数器变量;另外,经常会使用i、j、j这样的变量名,当然也可以使用更有意义的变量名。

while(true)就会进入死循环。

do-while语句:

do…while语句与while循环非常相似,但它是一种后测试循环语句,即先执行一遍循环体,之后再测试一个条件表达式;特点是循环体内的代码至少会被执行一次;

语法:

do{

statement;

}while(expression);

do/while语句

var i = 0;do{    i += 2;}while(i < 10);console.log(i);  // 10又如:function printArray(arr){    var len = arr.length, i = 0;    if(len == 0){        console.log("Empty Array");    }else{        do{            console.log(arr[i]);        }while(++i < len);    }}var arr = ["bejing","nanjing","shanghai"];printArray(arr);

do/while语句并不像while那么常用,这是因为在真实场景中很少会有要循环至少一次的情况;

注:注:while后面的分号(因为后置的while是一条语句,而前置的while是使用花括号的代码块);

for语句:

for语句比while更加方便和灵活的循环控制语句;其也是一种前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行代码的能力;即在已知循环次数的情况下,使用for循环比较合适;

语法:

for(initialize初始循环变量; test条件表达式; increment增量表达式)

{

statement;

}

初始循环变量:用于声明for循环中使用的变量并赋初始值,只是在循环开始时执行一次;

条件表达式:用于指定for循环结束的条件,每次循环时都判断该条件;

增量表达式:用于修改循环变量,每次循环都要执行;

可以称为三步曲:初始化、检测和更新(增量)。

for语句

for(var count = 0; count < 10; count++){    console.log(count);}// 等同var count = 0;while(count < 10){    console.log(count);    count++;}

使用while循环做不到的,使用for循环同样也做不到,也就是说,for循环只是把与循环有关的代码集中在了一个位置,简化了while循环;

var result = 1, i = 1;while(i <= 8){    result *= i;    console.log(i + "的阶乘为:" + result);    i++;}// 等同var result = 1;for(var i=1; i<=8; i++){    result *= i;    console.log(i + "的阶乘为:" + result);}

说明:在for中,increment表达式必须具有副作用,通常来讲,它不是一个赋值表达式就是一个递增或递减的表达式。

由于ECMAScript中不存在块级作用域,所以在循环内部定的变量也可以在外部访问到;如:

var count = 10;for(var i=0; i < count; i++){    var sum = i;    console.log(i);}console.log(i);console.log(sum);

在for循环的变量初始化表达式中,也可以不使用var关键字;该变量的初始化可以在外部执行;如:

var count = 10, i;for(i=0; i < count; i++)    console.log(i);

for语句中的初始化表达式、控制表达式和循环后表达式都是可选的;如果将这三个表达式全部省略,就会创建一个无限循环,如:

for(;;)    console.log("无限循环");

把初始化放到外部,把条件表达式及更新表达式放到内部,条件不满足使用break跳出循环,如:

var i = 0;for(;;){    console.log(i);    if(i >= 10){        break;    }    i++;}

如果只给出控制表达式,实际上就把for循环转换成了while循环,如:

var count = 10;var i = 0;for(; i < count;){    console.log(i);    i++;    // 必须有改变条件的语句,否则进入死循环}

说明:while底层就是for循环,while是for的简化版,但while与for并不完全等价,如在使用continue语句时。

可以有多个初始循环变量、条件表达式、增量表达式,此时需要用到逗号运算符,如:

var sum = 0;for(var i = 0, j = 1; i < 10; i++, j++){    sum += i * j;    console.log(i + "," + j);}console.log(sum);

for循环的执行顺序:

for(var i=0,j=console.log('a');console.log('b'),i<5;i++,console.log(i)){    console.log("w");}

由于for语句存在极大的灵活性,因此它也是ECMAScript中最常用的一个语句;

for(var i = 0, j = 1; i < 10; i++,j++){    document.write(i);    if(j % 4 == 0){        document.write("<br/>");    }}

在循环中,也并不是所有的循环变量是数字,如可以使用for循环来遍历链表数据结构,并返回链表中的最后一个对象:

function tail(o){  // 返回链表中最后一个节点对象    for(; o.next; o = o.next)  // 根据判断o.next是不是真值来执行遍历        return o;}var o = new Object();o.next = function(){};o.next.next = function(){};console.log(tail(o));

for-in语句:

for…in语句是一种精准的迭代语句,是和常规的for循环完全不同的循环(有些地方说是它是for语句的一个变体,其实是不准确的);通常用于遍历某个集合的每个元素,一般是数组或对象; 如列出对象的所有属性,操作数组的所有元素等。

语法:

for(variable in object) {

statement;

}

variable通常是一个变量名,也可以是一个可以产生左值的表达式或者一个通过var语句声明的变量,总之必须是一个适用于被赋值的变量(标识符);object是一个表达式,这个表达式的计算结果是一个对象;

for(var proName in window)    console.log(proName);console.log(window);

说明:使用for-in语句显示了BOM中window对象的所有属性;每次循环时,会将window对象中的一个属性赋值给变量proName;

for与for/in:

var arr = [];for(var i=0; i< 10; i++)    arr[i] = i * 10;for(var j = 0; j < arr.length; j++){    console.log(arr[j]);}for(var k in arr){    console.log("数组中的第"+k+"个元素是:" + arr[k]);}

说明:ES中的数组中是一种特殊的对象,因此使用for/in可以像枚举对象属性一样枚举数组索引;

注:与for语句类似,for-in中的var也不是必须的;但是,为了保证使用局部变量,推荐不要省略;

在实际应用中,for/in则是用来遍历对象属性成员:

var person = {    name : "wangwei",    age : 18,    sex : true,    walk : function(){        console.log("走路")    }}for(var p in person)    console.log("属性:" + p + ",值:" + person[p]);

注:ECMAScript对象的属性没有顺序,因此,通过for-in循环输出的属性名的顺序是不可预测的,具体来说,所有属性都会被返回一次,但返回的次序可能会因浏览器而异。

在执行for/in语句的过程中,JS解析器首先计算迭代对象object的表达式,如果其为null或undefined,在ES5之前,会抛出错误;第5版更正了这一行为,对这种情况不再抛出错误,而只是不执行循环体;为了保证最大限度的兼容性,建议在使用for-in循环之前,先检测确认该对象的值不是null或undefined;

如果object表达式等于一个原始值,这个原始值将会转换为与之对应的包装对象;

在每次循环之前,都会先计算variable表达式的值,并将属性名(一个字符串)赋值给它,因此它就是赋值表达式的左值,计算的结果值也有可能不同,如:把一个对象的所有属性复制到一个数组中:

var person = {    name : "wangwei", age : 18, sex : true,    walk : function(){        console.log("走路")    }}var a = [], i = 0;for(a[i++] in person);console.log(a);

for/in循环并不会遍历对象的所有属性,只有“可枚举”(enumerable)的属性才会遍历到;由JS核心语言定义的内置属性和方法就不是可枚举的,比如,所有对象都有方法toString(),但for/in并不枚举该方法;

而代码中定义的所有属性和方法都是可枚举的(当然,也可以让其变为不可枚举,后面我们会讲到);

循环的嵌套:

跳转:

ES中另一类语句是跳转语句(jump statement),即让ES执行可以从一个位置跳转到另一个位置;

标签(label)语句:

任何语句如果在前面加上标识符和冒号都可以构成标签语句,以便将来使用(即在程序的任何地方通过标签名引用这条语句);

语法:

label :statement

通常都是在if,while语句前使用,但必须是一个封闭的语句,如用{}封装的语句;如:

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

标签语句一般是与for、while循环语句配合使用;即在循环体内使用break和continute退出或跳转到标签外,二者是唯一可以使用标签的语句。

由于标签的命名空间与变量或函数的命名空间是不同的,所以可以使用同一个标识符作为标签名和作为变量或函数名,即可以同名;

另外,标签是可用在嵌套的代码中,但嵌套中的标签是不可以重名,如:

one: for(var i = 0; i<5; i++){    two: for(var j = 0; j<5; j++){        console.log(i+j);    }}

带有标签的语句还可以带有标签,即,任何语句可以有很多标签。

break语句:

单独使用break语句的作用是立即退出最内层的循环或switch语句(break也只能使用在循环或switch中);如:

for(var i = 0; i<5; i++){    console.log(i);    if(i==2) break;    }

break语句用于在循环中精确地控制代码的执行;其将无条件立即跳出并结束当前的循环结构(如果是嵌套循环,就跳出就近的循环体),并执行循环后面的语句;如:

var intNum = 0;for(var i = 1; i<10; i++){    if(i % 5 == 0) break;    intNum++;}console.log(intNum);

break与标签配合使用,退出当前循环的同时跳到标签处结尾处,即用以跳出多层嵌套的循环,如:

var num = 0;outerMost:for(var i=0;i<10;i++){    for(var j=0;j<10;j++){        if(i==5 && j == 5){            break outerMost;  // 与单独作用break        }        console.log(i + "," + j);        num++;    }}console.log(num);
var matrix = [[1,2,3],[2,3,4],[3,4,5]];  // 二维数组// 将矩阵中所有元素进行求和var sum =0, success = false;compute_sum:if(matrix){    for(var x = 0; x < matrix.length; x++){        var row = matrix[x];        if(!row) break compute_sum;        for(var y = 0; y < row.length; y++){            var cell = row[y];            if(isNaN(cell)) break compute_sum;            sum += cell;        }    }    success = true;}console.log(sum);

continue语句:

continue语句与break语句非常类似,区别在于它不退出循环,而是结束当前循环,执行下一次循环;其与break的用法基本一致。

但continue只能在循环体内使用;

for(var i=0;i<5;i++){    if(i==3) continue;    console.log(i);}

在不同类型的循环中,continue行为也有所区别:

在while循环中,在循环开始处指定的expression会重复检测,如果检测结果为true,循环体会从头开始执行;

在do/while循环中,程序的执行直接跳到循环结尾处,这时会重新判断循环条件,之后才会继续下一次循环;

在for循环中,首先计算自增表达式,然后再次检测test表达式,用以判断是否执行循环体;

在for/in循环中,循环开始遍历下一个属性名,这个属性名覆盖了指定的变量。

var data = [1,null,3,4];var total = 0;for(var i=0;i<data.length;i++){    if(!data[i]) continue;   // 不处理undefined数据    total += data[i];   }console.log(total);

continue与标签的配合使用与break一致;

注:虽然联用break、continue和label语句能够执行复杂的操作,但如果使用过滤,也会给调试带来麻烦;建议:少使用或不要嵌套过多的循环。

小示例:

// 计算2的n次幂,n可输入,n为自然数var mul = 1, n = 10;for(var i = 0; i < n; i++){    mul *= 2;}console.log(mul);// 计算n的阶乘,n可输入var mul = 1, n = 5;for(var i = 1; i<=n; i++){    mul *= i;}console.log(mul);//  斐波那契额数列 1 1 2 3 5 8 输出第n项,即a3 = a1 + a2// var n = parseInt(prompt('input'));var n = 6;var first = 1,    second = 1,    third;if(n > 2){    for(var i = 0; i < n - 2; i++){        third = first + second;        first = second;        second = third;    }    console.log(third);}else{    console.log(1);}// 输入a,b,c三个数字,打印出最大的// var a = parseInt(prompt('input'));// var b = parseInt(prompt('input'));// var c = parseInt(prompt('input'));var a=4,b=5,c=6,str="";if(a > b){    if(a > c){        str += a;    }else{        str += c;    }}else{    if(b > c){        str += b;    }else{        str += c;    }}console.log(str);// 打印出100以内的质数var count = 0;for(var i = 2; i < 100; i++){    for(var j = 2; j < i; j++){  // 除了1和它自身        if(i % j == 0){     // 能被其他数整除            count++;        }    }    if(count == 0){  // 说明是质数        document.write(i + " ");    }    count = 0;}

return语句:

return语句主要在函数内使用,即函数调用后的返回值,如:

return [expression];

return语句只能在函数体内使用,如果不是会报错;当执行到return语句的时候,函数终止执行,并返回exression的值,如:

function square(x){    return x * x;}console.log(square(2));  // 4

如果没有return语句,则函数调用返回的结果是undefined;

另外,return中的expression是可选的,如果省略expression,返回的也是undefined;如:

function display_object(o){    // 如果参数是null或undefined,则立即返回    if(!o) return;    // 其他逻辑    for(p in o){        console.log(p);    }}var person = {    name:"wangwei",    age:18}display_object(person);

with语句:

with语句的作用是将代码的作用域设置到一个特定的对象中。

语法:

with(object){

statement;

}

定义with语句的目的主要是为了简化多次编写同一个对象的工作,如:

var qs = location.search;var hostname = location.hostname;var url = location.href;// 上面的代码都使用了location对象,可以使用with语句改写with(location){    var qs = search;    var hostname = hostname;    var url = url;}console.log(qs);

说明:使用with语句关联了location对象,在with内部中,每个变量首先被认是一个局部变量,而如果在局部环境中找不到该变量的定义,就会查询location对象中是否有同名的属性,如果发现了同名属性,则以location对象属性的值作为变量的值;

with语句效率比较低,同时也会给调试代码造成困难,因此,在开发大型应用程序时,最好不要使用;

注:在严格模式下不允许使用with语句,否则将视为语法错误;

"use strict";with(document){    bgColor = 'purple';    fgColor = 'green';    write("背景是紫色的,文字是绿色的");}

with语句主要用于扩展作用域链,即把object添加到作用域链的头部,然后执行statement,最后把作用域链恢复到原始状态;

with(document.forms[0]){    name.value = "wangwei";    address.value = "南京市";    email.value = "admin@admin.com";}// 等价var form = document.forms[0];form.name.value = "wujing";form.address.value = "上海";form.email.value = "admin@admin.com";

说明:使用with把document.forms[0]添加至作用域的最顶层;

debugger语句:

debugger语句通常什么也不做;然而,当调试程序可用并运行的时候,JS解析器将会以调试模式运行,此时,这条语句会产生一个断点(breakpoint),js代码的执行会停止在断点的位置,这时可以使用调试器输出变量的值,检查调用栈等。

如,假设由于调用函数f()的时候使用了未定义的参数,因此f()抛出一个异常,但无法定位到底是哪里抛出了异常;为了有助于调试这个问题,需要修改函数f(),如:

function f(o){    if(o === undefined) debugger;  // 此行只用于临时调试    console.log("其他执行代码");}f();

此时,程序将停止执行,可以通过调试器检测调用栈并找出错误产生的原因。

“use strict”严格模式:

“use strict”是ES5引入的一条指令,指认不是语句(但非常接近于语句),其和普通的语句之间有两个重要的区别:

1) 它不包含任何语言的关键字,指令仅仅是一个包含一个特殊字符串直接量的表达式,对于那些没有实现ES5的JS解析器来说,它只是一条没有副作用的表达式语句,它什么也没做;将来的ES标准希望将use用作关键字,这样就可以省略引号了。

2) 它只能出现在脚本代码的开始或者函数体的开始、任何实体语句之前;但它不必一定出现在脚本的首行或函数体内的首行,因为“use strict”指令之后或之前都可能有其他字符串直接量表达式语句,并且JS的具体实现可能将它们解析为解释器自有的指令;有脚本或函数体内第一条常规语句之后字符串直接量表达式语句只当做普通的表达式语句对待;它们不会当做指令解析,它们也没有任何副作用。

ES5的严格模式是该语言的一个受限制的子集,它修正了语言的重要缺陷,并提供健壮的查错功能和增强的安全机制。严格与非严格模式之间的区别:

1)严格模式禁止使用with语句;

2)在严格模式中,所有的变量都要先声明;

3)在严格模式中,调用的函数(不是方法)中的一个this值是undefined;而在非严格下,此this值总是全局对象;可以利用这种特性来判断JS实现是否支持严格模式:

var hasStrictMode = (function(){"use strict"; return this===undefined}());

console.log(hasStrictMode);

4)在严格模式中,当通过call()或apply()来调用函数时,其中的this就是这两个方法传入的第一个参数,在非严格模式下,null和undefined值被全局对象和转换为对象的非对象值所代替。

5)在严格模式中,给只读属性赋值和给不可扩展的对象创建新成员都将抛出一个类型错误异常,在非严格模式下,这些操作只是简单的操作失败,不会报错。

6)在严格模式中,传入eval()的代码不能在调用程序所在的上下文中声明变量或定义函数,而在非严格模式中是可以这样做的;相反,变量和函数的定义是在eval()创建的新作用域中,这个作用域在eval()返回时就弃用了。

7)在严格模式中,函数里的arguments对象拥有函数值的静态副本;在非严格模式中,arguments对象具有“魔术般”的行为,它的数组元素和函数参数都是指向同一个值的引用。

8)在严格模式中,当delete运算符后跟非法的标识符(比如变量、函数、函数参数)时,将会抛出错误,在非严格模式中,这种delete表达式什么也没做,并返回false;

9)在严格模式中,试图删除一个不可配置的属性将抛出错误,在非严格模式中,delete表达式操作失败,并返回false;

10)在严格模式中,在一个对象直接量中定义两个或多个同名属性将产生一个语法错误,反之不会;

11)在严格模式中,函数声明中存在两个或多个同名的参数将产生一个语法错误,反之不会;

12)在严格模式中是不允许使用八进制整数直接量,反之允许;

13)在严格模式中,标识符eval和arguments当做关键字,它们的值是不能更改的,不能赋值,也不能把它们声明为变量、用作函数名、参数或用做catch块的标识符;

14)在严格模式中限制了对调用栈的检测能力;在函数中,arguments.caller和arguments.callee都会抛出异常;严格模式的函数册样具有caller和arguments属性,当访问这两个属性时将抛出异常。

Web前端开发之Javascript-零点程序员-王唯

标签: #js中循环语句关键字是