流程控制语句

  1. 表达式

    **表达式是js中的短语,解释器遇到短语的时候,会根据表达式中的内容以及它所包含的操作符来计算出来一个结果。**js中每一个短语,或者每一个用空格分开的东西都是一个表达式。

    表达式就是js中的一个短语,解释器遇到短语后会把它计算出来一个结果,参与运算。我们把这种参与运算的各种短语叫做表达式。

  2. 语句

    语句是js中的命令,当你执行语句的时候肯定会发生某一些事情,比如创建、修改、删除。我们把在js当中会促使某件事情发的命令称之为语句。

  3. 作用

    二元加操作符的作用:让两个数字相加或者两个字符串拼接。+ - < >

  4. 副作用

    当你去运行一个语句或者执行一个表达式的时候,他对某些变量的值进行了修改、删除、增加的操作叫做副作用。++ 、-- =赋值语句都有副作用。

语句

表达式不一定有副作用,语句一定有副作用

在js程序当中,整个程序的运行就是一系列语句的合集。解释器根据语句的顺序从上先下执行,这个从上向下执行的过程叫流程。解释过程需要对流程进行一些控制,参与到流程控制的js语句,叫流程控制语句。语句的结束用分号;

基础语句

  • 表达式语句

    在js中如果一个表达式带有副作用。也就是说这个表达式对它所处理的操作数进行了值的增删改,这时这个表达式就叫做表达式语句。表达式语句还是要使用分号;把它结束。

    递增、递减、赋值语句= +=、delet操作符(只能删除对象的属性)

    函数调用表达式

    ++a; a--; --a; a++; a=1; a+=1; delet Object.a;  func();
    
  • 复合语句和空语句

    • 复合语句是把很多语句放在一起当作一个语句使用。使用 {} 把几条语句括起来,连同{}就组成了复合语句,也叫语句块。

      • 复合语句的作用

        因所有的流程控制语句都是在执行一个判断之后去执行它后面的一条语句。复合语句相当于把多条语句合并为一条语句。

    if后面的{}的作用是把多条语句当成一条语句。不使用{}只会执行第一条语句。

    {}中定义的变量作用域不在{}中,而是在它所在的函数作用域中。

    js中只有函数作用域,没有块作用域。

    • 空语句

      只有一个;分号的语句叫做空语句。解释器遇到空语句什么都不做;

      复合语句大括号{}的结尾可以使用分号;解释器会当作空语句来使用。

      代码模块开头使用;空语句,防止合并压缩后产生错误。

  • 声明语句

    声明语句是在js中声明一个变量,或声明一个函数。

    • var 定义变量

      1. 变量作用域是所处函数作用域,并不是{}

      2. 变量不可以使用delet操作符删除的,只会在它所处的函数运行结束后被系统的垃圾回收机制处理回收掉。

        不使用var定义的变量实际上是在win上增加一个属性是可以使用delet操作符删除的

      3. var 定义变量时可以不设定初始值。var a; 默认初始值是undefined

      4. 可以使用逗号,定义多个变量。var a=2,b,c=2

      5. 变量声明提前;js解释器运行时会有一个预处理过程,预处理过程会把变量名字提前到整个作用域最顶上。如果是在一个函数中定义变量,这个时候会定义变量名字的操作会被提升到函数的最顶上。这种行为叫变量声明提前。

        alert(a) //undefined
        var a=1
        alert(a) // 1
        //实际过程 var a=1 被分为 var a; a=1;两行代码
        var a
        alert(a)
        a=1
        alert(a)
        

        建议:函数中定义变量都放在最上面

    • function定义函数

      1. 正常定义

        function name(){}
        //{}不能省略
        

        跟定义变量一样都不可以使用delet操作符删除

        声明提前: 整个函数体都会被提前。

        建议:提前定义

      2. 匿名函数赋值给变量形式的函数声明

        var funName = function(){}
        ///
        var funName;
        funName = function(){}
        

        区别:变量命名函数,函数体不会提前,变量名提前。

        不要在if 和while 中定义函数

分支语句

  • if语句

    if (condition) statement1 else statement2
    

    condition(条件)可以是任意表达式,而且对这个表达式求值的结果不一定是布尔值。ECMAScript 会自动调用 Boolean()转换函数将这个表达式的结果转换为一个布尔值。如果对 condition求值的结果是 true,则执行 statement1 (语句 1),如果对 condition 求值的结果是 false,则执行 statement2(语句 2)。而且这两个语句既可以是一行代码,也可以是一个代码块(以一对花括号括起来的多行代码)

    if() //()必须的,()中可以书写任意表达式。执行紧跟在后面的一条语句
    else //执行紧跟在后面的一条语句
       //多条语句用复合语句{}把多条语句放在里面。  
    

    建议:

    1. 尽量使用{}把执行语句放在里面。除非只有一条语句
    2. if语句的()中进行数值比较时(基础数据类型比较都是数值比较)使用===比较,减少类型转换提高性能,提交准确性。
  • switch语句(多分枝语句)

    switch (expression) { //expression可以是任何类型表达式,不进行数据类型的转换
        case value: statement 
        //表达式expression的值跟case的值value===全等时才会运行后面的代码statement
        //case的值value可以是变量、常量、表达式。只要值跟expression全等===
        	break;
        case value: statement
        	break;
        case value: statement
        	break;
        case value: statement
        	break;
        default: statement
    }
    

    switch 语句中的每一种情形(case)的含义是:“如果表达式等于这个值(value),则执行后面的语句(statement)”。而 break 关键字会导致代码执行流跳出 switch 语句。如果省略 break 关键字,就会导致执行完当前 case 后,继续执行下一个 case。最后的 default 关键字则用于在表达式不匹配前面任何一种情形的时候,执行机动代码(因此,也相当于一个 else 语句)case后面的值可以是 变量、常量、表达式只要跟expression返回的值全等就会执行case后面的语句。case 通常是常量。

    switch (true) {
        case (a>10): statement
        	break; // break中断语句。
            //停掉整个switch语句。只是结束当前switch语句不影响外层
        case (a>5): statement
        	break;
        case (a>1): statement
        	break;
        default: statement //所有的case都没有匹配时执行,通常在最下面,可以放在switch中的任何地方
    }
    

循环语句

  • while循环语句

    while(expression) statement
    

    先执行()中的表达式,然后把表达式的结果转化为布尔类型。如果表达式的结果为true,就运行后面的代码。如果为false,就跳过这个语句运行后面的代码。

    与if语句不同:

    while的循环体statement运行完后,会回过头重新计算()中的表达式,如果表达式的结果还是true,就再运行循环体statement的代码。直到()中的表达式为false。

    var a=1
    while(a<=100){
    	console.log(a)
    	a++ //对表达式的值进行修改
    }
    
  • for循环语句

    for (initialization1; expression2; post-loop-expression3) statement4
    
    • 执行顺序

      for循环的()中有三个用分号;分开的表达式。

      第一个表达式: 初始化1

      第二个表达式:判断2

      第三个表达式:更新3

      括号后面执行语句statement:执行4

      执行顺序:1初始化》2判断 》4执行 》3更新 》2判断》4执行》3更新

    • 初始化过程

      js中不存在块级作用域,for循环中初始化定义的变量在for循环语句所在的函数体内都可以访问。初始化的表达式可以放在for循环语句外面定义。它只用了一次。

    • 判断过程

      运行第二个表达式,将结果转化为布尔类型。(所有的值都可以转化为布尔类型,所以可以写任何的表达式)。如果不写第二个表达式就不会进行判断直接for循环中的代码,会形成死循环。可以直接使用返回值是布尔类型的表达式可以减少数据类型转换提高性能 直接进行值的比较,不要使用表达式跟值的比较。

      var i=0 ,len= list.length
      for(;i<len;i++){ //避免每次循环都进行数组取值的计算,提高性能
          console.log(i)
      }
      
    • 更新过程

      更新过程也可以为空,但会死循环

    for循环和while循环比较:

    两者可以相互转化,性能上没有差别。只是书写形式不同。

    • 初始化

      for的初始化可以放外面,就跟while一样直接进行判断

    • 更新

      for循环更新在()第三个表达式上,while在纸箱体内

  • for-in循环语句

    for (property in expression) statement
    

    for-in循环是一个更精准的迭代语句,效率更低。用来枚举对象的属性。

    js解释器在遇到for-in语句是先对()中in后面的表达式进行操作,把表达式的结果转化为对象(for-in就是来枚举对象属性的)。

    执行过程:

    1. 对象的转换

      解释器首先会对表达式执行的结果进行一个判断,判断一下它的数据类型,

      如果数据类型是null和undefind 就报错或ES5跳过。

      如果是其他的基础数据类型数字、字符串、布尔类型解释器会先把他们转化为包装对象然后再执行后面的操作。

    2. 赋值

      运行in前面的表达式,并且把对象的某一个属性取出来把这个属性的名字赋值给前面的表达式的结果。赋值完成执行整个代码循环体。然后继续执行赋值操作。

    注意:

    1. in前面可以是任意表达式,但结果一定是个左值:可以被赋值的值。变量或对象的属性。

    2. in前面的表达式在每次循环的时候都会被执行一次。

      var a=[],i=0
      for (a[i++] in onject);
      
    3. in后面可以是原始数据类型非null和undefin

      var a=[],i=0
      for (a[i++] in 12); //a=[]
      var a=[],i=0
      for (a[i++] in true); //a= []
      

      数字和布尔类型整个循环不会进行任何操作,因布尔和数字类型转化为包装对象后是没有任何的可以被列举出来的属性。只有一个属性原始值,但这个原始值不能被枚举。

      var a=[],i=0
      for (a[i++] in "qweqwe"); //a=["0", "1", "2", "3", "4", "5"]
      

      字符串转换为字符串包装对象时,包含从0开始的索引,每个值对应字符串的字符。length长度和原始值。只有字符对应的索引可以被枚举出来。

    4. js内置的一些属性和方法是不可以被枚举出来的。

      toString() ,valueOf(), 字符串包装对象的length属性,包装对象的原始值

    5. 对象的属性和方法是继承与其他对象,继承的方法和属性也会被枚举出来

      只要对象自己的属性需进行一个判段

    6. 循环体中动态增加或者删除了还没有被被枚举出来属性,这个属性在接下来的循环过程中不会被枚举出来。

    7. 枚举的顺序,一半按属性定义的顺序枚举

    8. 如果对象具有整数的属性,那么在进行for-in循环的时候会按照数子的顺序枚举出来

      for-in用于数组

中断语句

  • break语句

    退出当前循环或switch语句,只有在循环语句和switch语句中使用才是合法的。

    • switch语句中的使用

      switch是一个多条件的分支语句,当某一个条件成立的时候,去执行一个功能。如果执行完这个功能后不再运行其他语句就需要使用break语句(一般匹配一个后就不会再匹配其他)。解释器在遇到break后会结束整个switch语句。

    • 循环语句

      在循环语句中如果希望当某个条件成立后就结束这个循环就要使用break语句。

      for(var i=1000; i>0;i--){
          if(i=质数){
              console.log(i);
              break;
          }
      }
      

      作用范围:当解释器遇到break时它结束的只是当前循环或当前switch语句。

      break相当于在游乐场中结束某个项目,如过你问一句我下一步到哪就用到了标签语句

      多重循环嵌套结构也只结束当前循环,外层循环不会结束。如果想结束就用到了标签语句。

  • 标签语句

    标签语句跟break语句一起使用。

    1. 打标签

      标签名加冒号,标签名非js关键字和保留字。冒号后跟一个语句或者语句块,我们把冒号后面的语句叫做目标语句

      name:console.log("目标语句")
      
    2. 使用标签

      在break后面空格跟上标签的名字。

      break结束后跳转到标签语句所对应的语句结尾,不是跳转到标签语句。

    for(var i=1000; i>0;i--){
        if(i=8){
            console.log(i);
            break name
        }
    }
    //跳转到结尾
    name : 
    
  • return

    js中所有变量的作用域都是它所在的函数,break配合标签语句也不能跳出它所在的函数。如果要跳出函数就要用到return语句。

    return结束所在函数,并返回一个结果也叫函数返回值。返回值可以是任何数据类型也可不返回任何东西。

    return 返回的是它后面的并且跟他在同一行的表达式。

    break是用来结束语句的,return是用来结束函数的。

  • continue语句

    同break语句一样都是在循环语句和switch语句中使用,也可以和标签语句配合使用。作用范围也是它所处的语句。

    • 在循环语句中break是直接停止整个循环语句,continue 停止当前循环进入下一次循环。

    • 在switch语句中break是结束整个switch语句,continue是结束当前case(分支)进行下一个case(分支)比较

    可阅读性不好,不建议使用。

  • srow

    遇到srow时整个js停止运行,开始在附近寻找异常处理程序,一层层向上找直到程序最顶层。一般结合try chatch语句使用