JavaScript提升系列(六):语句

本文总结

  • ECMAScript中不存在块级作用域,因此循环内部定义的变量也可以在外部访问到。(ES6中新增let关键字,可以定义块级作用域的变量)
  • ECMAScript中的对象没有顺序,因此通过for-in语句遍历对象属性的顺序是不可预测的。
  • 如果迭代的对象值为nullundefined,ES5以上不执行循环体。(ES5以下会抛出错误)
  • 大量的with语句会造成性能问题,在大型应用中,不建议使用with语句。

与C++/Java不同之处

  • 用于循环嵌套场景的break <label>continue <label>语句。(C/C++虽然有这个语句,但一般与goto搭配使用,不能和breakcontinue使用)
  • with语句,限定语句作用域于某个对象。(C++没有此语句)
  • switch语句可以用于任意类型,每个case的值可以是常量,变量,字符串,对象,甚至是表达式。(C++中,只能为整型家族的值)

严格模式

  • 严格模式下,不允许使用with语句,将会被视为语法错误。

——————————————正文分割线——————————————————

if 语句

大多数编程语言中最常用的一个语句就是if语句,以下是if语句的用法:

if( condition ){
  statement1
}
else {
  statement2
}

其中condition可以是任意表达式,而且表达式求值的结果不一定是布尔值,ECMAScript会自动调用Boolean()转换函数将这个表达式的结果转换为布尔值。

do-while语句

do-while语句是一种后测试循环语句,只有在循环体中的代码执行之后,才会测试出口条件,以下是其用法:

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

while语句

while语句属于前测试循环语句,也就是说,在循环体代码被执行之前,就会对出口条件求值,以下是其用法:

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

for语句

for语句也是前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行的代码的能力,以下是其用法:

var count = 10;
for ( var i=0; i<count; ++i ) {
  alert(i);
}

for循环语句与下面的while语句功能相同:

var count = 0;
var i = 0;
while ( i<count ){
  alert(i);
  ++i;
}

使用while循环做不了的,使用for循环同样也做不到。
for循环的变量初始化表达式中,也可以不使用var关键字,该变量的初始化可以在外部执行,例如:

var count = 10;
var i;
for ( i=0; i<count; ++i ){
  alert(i);
}

以上代码在循环初始化表达式中声明变量的效果是一样的。
由于ECMAScript中不存在块级作用域,因此循环内部定义的变量也可以在外部访问到,例如:

var count = 10;
for ( var i=0; i<count; ++i ){
  alert(i);
}
alert(i);    //  i = 10

在这个例子里,会有一个警告框显示循环完成后变量i的值,这个值是10。
这是因为,即使i是在循环内部定义的一个变量,但在循环外部仍然可以访问它。
此外,for语句中的初始化表达式、控制表达式和循环后表达式都是可选的,将两个表达式全部省略,就会创建一个无限循环,例如:

for (; ; ;) {
  doSomething();
}

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

var count = 10;
var i = 0;
for (; i<count; ) {
  alert(i);
  ++i;
}

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

for-in语句

for-in语句是一种精准的迭代语句,可以用来枚举对象的属性,以下是for-in语句的用法:

for ( var propName in window ) {
  document.write(propName);
}

for语句类似,这里控制语句中的var操作符也不是必需的,但为了保证使用局部变量,我们推荐上面例子中的这种做法。
ECMAScript对象的属性没有顺序,因此通过for-in语句循环输出的属性名顺序是不可预测的

label语句

使用label语句可以在代码中添加标签,以便将来使用,以下是其用法:

start : for ( var i=0; i<10; ++i ) {
  alert(i);
}

这个例子中定义的start标签可以在将来由breakcontinue语句引用,加标签的语句一般都与for语句等循环语句配合使用。

break和continue语句

breakcontinue语句用于在循环中精确地控制代码的执行。
break,立刻退出循环。
continue,退出本次循环,进入下次循环。
使用break例子如下:

var num = 0;
for ( var i=1; i<10; i++ ) {
  if ( i%5==0 ){
    break;
  }
num++;
}
alert(num);    //4

使用continue例子如下:

var num = 0;
for ( var i=0; i<10; ++i ){
  if ( i%5==0 ) {
    continue;
  }
  num++;
}
alert(num);  //8

breakcontinue语句都可以与label语句联合使用,从而返回代码中特定的位置,这种联合使用多用于循环嵌套的情况下,如下例:

var num = 0;
outerLabel:
  for( var i=0; i<10; ++i ){
    for( var j=0; j<5; ++j ){
      if( j==2 ){
        break outerLabel;
      }
      num++;
    }
  }
alert(num);    //2

上述例子中,在内层循环时,判断j变量等于2的时候,进行break,此处的break指定了一个outerLabel,意味着,从outerLabel标记的循环中进行break,因此上述的嵌套循环只执行了2次。

with语句

with语句的主要作用是将代码的作用域设置到一个特定的对象中。
不使用with的情况:

var gs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href; 

使用with语句简化代码:

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

上述例子中,每个变量首先被认为是局部变量,如果局部变量中找不到该变量的定义,就会查询location对象中是否有同名的属性。
严格模式下不允许使用with语句,否则将视为语法错误。
大量使用with语句会导致性能下降,同时也会被代码调试造成困难,因此在开发大型应用程序时,不建议使用with语句。

Switch 语句

switch语句与if语句的关系最为密切,而且也是其他语言中普遍使用的一种流控制语句,例子如下:

switch (i) {
  case 25:
    alert("25");
    break;
  case 35:
    alert("35");
    break;
  default:
    alert("other");
}

ECMAScript中的switch语句可以用于任何数据类型,无论是字符串还是对象都没有问题,其次每个case值不一定是常量,可以是变量,甚至是表达式。

switch ("Hello World") {
  case "Hello "+ "World":
    alert("Greeting was found!");
    break;
  case "goodBye":
    alert("Closing was found!");
    break;
  default:
    alert("Unexpected message was found!");
}

除上述例子外,使用表达式作为case值还可以实现下列操作:

var num = 25;
switch (true) {
  case num < 0:
    alert("Less than 0");
    break;
  case num>=0 && num <=10:
    alert("Between 0 and 10.");
    break;
  case num>10 && num<=20:
    alert("Between 10 and 20.");
    break;
  default:
    alert("More than 20.");
}

之所以给switch语句传递表达式true是因为每个case值都可以返回一个布尔值。
switch语句在比较值时,使用的是全等操作符,因此不会发生类型转换。

完!

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335