【JS高级程序设计】第三章 基本概念

【JS高级程序设计】第三章 基本概念

3.1语法

  • 区分大小写

  • 不能使用关键字/保留字

  • 统一的命名规则

    第一个字符必须是一个字母、下划线(_)或一个美元符号($); 其他字符可以是字母、下划线、美元符号或数字。 标识符中的字母也可以包含扩展的 ASCII 或 Unicode 字母字符(如 À 和 Æ),但我们不推荐这样做。

    ECMAScript 标识符采用驼峰大小写格式:

    firstSecond myCar doSomethingImportant

    虽然没有谁强制要求必须采用这种格式,但为了与 ECMAScript 内置的函数和对象命名格式保持一 致,可以将其当作一种最佳实践。

  • 注释:单行/多行注释 // or /* */

  • ECMAScript5 提出严格模式:’use strict’ , 也可在函数内部执行

  • 语句:推荐语句用分号结束

  • 变量:

    //创建局部变量
    function test(){
      var msg = '1'
    }
    alert(msg) //抛出错误
    
    //创建全局变量
    function test(){
      msg = '1'
    }
    alert(msg) // 1

3.4数据类型

  • 5种简单类型:Undefined、Null、Number、String、Boolean
  • 一种复杂类型:Object

3.4.1 typeof操作符

typeof负责检测数据类型,以下为数据检测返回值:

  • “undefined” // 如果这个值未定义
  • “object” //如果这个值为对象或者Null
  • “number” //如果这个值为数值
  • “string” //如果这个值为字符串
  • “boolean” //如果这个值为true/false
  • “function” // 如果这个值为函数

typeof(msg) 注意, typeof 是一个操作符而不是函数,因此例子中的圆括号尽管可以使用,但不是必需的

3.4.2 Undefined类型

undefined 只有一个值就是undefined,在var进行声明未进行赋值的情况下,返回undefined。

var msg ; // 等价与var msg = undefined
alert( msg === undefined) //true
alert(age) //产生错误

用typeof检测数据类型时,已定义和未定义的都返回undefined

var msg;
console.log(msg) //undefined
console.log(age) //undefined

3.4.3 Null类型

Null 类型是第二个只有一个值的数据类型,这个特殊的值是 null。从逻辑角度来看,null 值表 示一个空对象指针,而这也正是使用 typeof 操作符检测 null 值时会返回”object”的原因

Null类型只有一个值就是null,null对象表示一个空对象指针,在定义一个位置obj的时候就可以使用null进行预定义

var person = null;
console.log(typeof person ) //object 通常用来定义一个空对象

实际上,undefined 值是派生自 null 值的,因此 ECMA-262 规定对它们的相等性测试要返回 true:

null == undefined
//实际上进行了转换
Boolean(null) == Boolean(undefined)
//true

null常用在初始化一个对象

只要意在保存对象的变量还没有真正保存对象,就应该明确地让该变量保存 null 值。这样做不仅可以 体现 null 作为空对象指针的惯例,而且也有助于进一步区分 null 和 undefined。

3.4.4 Boolean类型

值:true / false 区分大小写

所有类型都有一个boolean 的值,转换方式:

var msg = 'hello world'
var msgBoolean = Boolean(msg)

所有值转换列表:

数据类型 转换为true的值 数量
Boolean true 5
String 任何非空字符串 “” /空字符串
Number 任何非零数字值(包括无穷大) 0和NaN
Object 任何对象 null
Undefined n/a(not applicable 的缩写“不适用”) undefined

3.4.5 Number类型

  • 浮点数值

    由于保存浮点数值需要的内存空间是保存整数值的两倍,因此 ECMAScript 会不失时机地将浮点数值 转换为整数值。显然,如果小数点后面没有跟任何数字,那么这个数值就可以作为整数值来保存。同样 地,如果浮点数值本身表示的就是一个整数(如 1.0),那么该值也会被转换为整数,如下面的例子所示:

    var floatNum1 = 1.; var floatNum2 = 10.0;
    // 小数点后面没有数字——解析为 1 
    // 整数——解析为 10
    
    //指数幂计数法:
    var count = 3.159e4 //31590
    //在默认情况下,ECMASctipt 会将那些小数点后面带有 6个 零以上的浮点数值转换为以 e 表示法表示的数值(例如,0.0000003 会被转换成 3e7)。
    
    console.log(0.1+0.2) //结果为 0.30000000000000004
    //永远不要做浮点数相加判断
  • 数值范围

    ECMAScript 能够表示的最小数值保 存在 Number.MIN_VALUE 中——在大多数浏览器中,这个值是 5e-324;能够表示的最大数值保存在 Number.MAX_VALUE 中——在大多数浏览器中,这个值是 1.7976931348623157e+308。如果某次计算的 结果得到了一个超出 JavaScript 数值范围的值,那么这个数值将被自动转换成特殊的 Infinity 值。具 体来说,如果这个数值是负数,则会被转换成-Infinity(负无穷),如果这个数值是正数,则会被转 换成 Infinity(正无穷),

    。要想确定一个数值是不是有穷的(换句话说,是不是位于最 小和最大的数值之间),可以使用 isFinite()函数。这个函数在参数位于最小与最大数值之间时会返 回 true,如下面的例子所示:

    var result = Number.MAX_VALUE + Number.MAX_VALUE;
    alert(isFinite(result)); //超出范围false
  • NaN

    任何涉及NaN的操作都会返回NaN,NaN与自己不相等

    检测一个值是否为NaN的函数: isNaN();

    任何涉及 NaN 的操作(例如 NaN/10)都会返回 NaN,

  0 / 0 // NaN
  8 / 0 //Infinity
  //使用isNaN()检测是否不是数值
  console.log(isNaN(true)) // boolean true自动转换为1,是数字返回false
  alert(isNaN(NaN));//true
  alert(isNaN(10));//false(10 是一个数值)
  alert(isNaN("10"));//false(可以被转换成数值 10)
  alert(isNaN("blue"));//true(不能转换成数值)
  • 数值转换

    • Number()函数

      • 可转换所有类型
      • 如果是boolean true ->1 / false ->0
      • 数字,简单传入传出
      • null -> 0
      • undefined -> NaN(不是数字)
      • 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即”1” 会变成 1,”123”会变成 123,而”011”会变成 11(注意:前导的零被忽略了)
      • 如果字符串中包含有效的浮点格式,如”1.1”,则将其转换为对应的浮点数值(同样,也会忽 略前导零);
      • 如果字符串中包含有效的十六进制格式, 例如 “0xf” , 则将其转换为相同大小的十进制整 数值;
      • 如果字符串是空的(不包含任何字符),则将其转换为 0;
      • 如果字符串中包含除上述格式之外的字符,则将其转换为 NaN。
      • 如果是对象,则调用对象的 valueOf()方法,然后依照前面的规则转换返回的值。如果转换 的结果是 NaN,则调用对象的 toString()方法,然后再次依照前面的规则转换返回的字符 串值。
      //示例
      Number('hello world') // NaN
      Number(null) // 0
      Number("011") // 11
      Number(true) // 1
      Number(undefined) //NaN
    • parseInt() 函数

      由于 Number()函数在转换字符串时比较复杂而且不够合理,因此在处理整数的时候更常用的是 parseInt()函数。parseInt()函数在转换字符串时,更多的是看其是否符合数值模式。

      parseInt()会替换掉空格,会忽略前导的0,如果字符串开头为字符则返回NaN。

      parseInt("") //空字符串返回NaN
      parseInt("123abc") //123
      parseInt("abc123") //NaN

      parseInt(‘’,进制)

      接收一个进制,按照进制进行转换

    • parseFloat()函数

      只解析10进制的数字,忽略前导的0

3.4.6 String类型

  • 字符串字面量

    反斜杠表示转义字符

    \n 换行
    \t 制表
    \b 空格
    \r 回车
    \f 进纸
    \\ 斜杠
    \' 转义'
    \" 转义"
    \xnn 以十六进制代码nn表示的一个字符(其中n为0~F)。例如,\x41表示"A"
    \unnnn 以十六进制代码nnnn表示的一个Unicode字符(其中n为0~F)。例如,\u03a3表示希腊字符Σ
  • 字符串的特点

    ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变 某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量, 例如:

    var lang = "Java";
    lang = lang + "Script";
  • 转换字符串

    • toString()方法,可以接收一个参数─进制
    var age = 13;
    var ageAsString = age.toString(8); // 以8进制处理返回"15"

    数值、布尔值、对象和字符串值(没错,每个字符串也都有一个 toString()方法,该方法返回字 符串的一个副本)都有 toString()方法。但 null 和 undefined 值没有这个方法。

    • String() 方法
    • 如果值有 toString()方法,则调用该方法(没有参数)并返回相应的结果;

    • 如果值是 null,则返回”null”;

    • 如果值是 undefined,则返回”undefined”。

      var value1 = 10;
      var value2 = true;
      var value3 = null;
      var value4 ;
      
      String(value1) // "10"
      String(value2) // "true"
      String(value3) // "null"
      String(value4) // "undefined"
    • 要把某个值转换为字符串,可以使用加号操作符把它与一个字符 串(””)加在一起。

3.4.7 Object类型

ECMAScript 中的对象其实就是一组数据和功能的集合。对象可以通过执行 new 操作符后跟要创建 的对象类型的名称来创建。而创建 Object 类型的实例并为其添加属性和(或)方法,就可以创建自定 义对象,

var obj = new Object(); 

Object 的每个实例都具有下列属性和方法。

  • constructor:保存着用于创建当前对象的函数。对于前面的例子而言,构造函数(constructor) 就是 Object()。
  • hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例 的原型中)是否存在。其中,作为参数的属性名(propertyName)必须以字符串形式指定(例 如:o.hasOwnProperty(“name”))。
  • isPrototypeOf(object):用于检查传入的对象是否是传入对象的原型。
  • propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用 for-in 语句来枚举。与 hasOwnProperty()方法一样,作为参数的属性名必须以字符串形式指定。
  • toLocaleString():返回对象的字符串表示,该字符串与执行环境的地区对应。
  • toString():返回对象的字符串表示。
  • valueOf() :返回对象的字符串、数值或布尔值表示。 通常与 toString() 方法的返回值相同。

3.5 操作符

ECMA-262 描述了一组用于操作数据值的操作符,包括算术操作符(如加号和减号)、位操作符、 关系操作符和相等操作符。ECMAScript 操作符的与众不同之处在于,它们能够适用于很多值,例如字 符串、数字值、布尔值,甚至对象。不过,在应用于对象时,相应的操作符通常都会调用对象的 valueOf() 和(或)toString()方法,以便取得可以操作的值。

3.5.1 一元操作符

只能操作一个值的操作符叫做一元操作符。一元操作符是 ECMAScript 中最简单的操作符。

  • 前置递增和递减操作

    ++ / –

    ++ age ;
    -- age;
    //执行前置递增和递减操作时,变量的值都是在语句被求值以前改变的。(在计算机科学领域,这种 情况通常被称作副效应。)
    
    var age = 29 ;
    var anotherAge = --age + 2;
    //输出 age 28 anotherAge 30 
    

//由于前置递增和递减操作与执行语句的优先级相等,因此整个语句会从左至右被求值
var num1 = 2;
var num2 = 20;
var num3 = –num1 + num2; //21
var num4 = num1 + num2; //21


  >   加号/减号在前,先计算值,然后再计算表达式,值先增加/减少
  >
  >   加号/减号在后,先计算表达式,然后再计算值,值后增加/减少



* 后置递增和递减操作

  ```js
  var num1 = 2
  var num2 = 20

  var total = num1 ++ +num2  // 22
  num1  //3

  var total = num1 -- +num2  // 23
  num1 //2
  • 在应用于不同的值时,递增和递减操作符遵循下列规则:

    1. 在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减 1 的操作。字 符串变量变成数值变量。
    2. 在应用于一个不包含有效数字字符的字符串时,将变量的值设置为 NaN 字符串变量变成数值变量。
    3. 在应用于布尔值 false 时,先将其转换为 0 再执行加减 1 的操作。布尔值变量变成数值变量。
    4. 在应用于布尔值 true 时,先将其转换为 1 再执行加减 1 的操作。布尔值变量变成数值变量。
    5. 在应用于浮点数值时,执行加减 1 的操作。
    6. 在应用于对象时,先调用对象的 valueOf()方法以取得一个可供操作的 值。然后对该值应用前述规则。如果结果是 NaN,则在调用 toString()方法后再应用前述规 则。对象变量变成数值变量。

    市例:

    var a = "1"
    a ++ // 1
    a //2
    typeof a  // number
    
    var b = "str" 
    b ++ // NaN
    b //NaN
    typeof b //number
    
    var c = false
    c++ // 0
    c // 1
    typeof c // number
    
    var d = true
    d++ // 1
    d // 2
    typeof d //number
    
    var e = 1.1
    e ++ // 1.1
    e // 2.1
    typeof e // number
    
    var o = {
      valueOf : function(){
        return 1
        }
    }
    o ++ // 1
    o // 2 
    typeof o // number

3.5.2 位操作符

对于有符号的整数,32 位中的前 31 位用于表示整数的值。第 32 位用于表示数值的符号:0 表示正 数,1 表示负数。这个表示符号的位叫做符号位,符号位的值决定了其他位数值的格式。其中,正数以 纯二进制格式存储,31 位中的每一位都表示 2 的幂。第一位(叫做位 0)表示 2 0 ,第二位表示 2 1 ,以此 类 推 。 没 有 用 到 的 位 以 0 填 充 , 即 忽 略 不 计 。 例 如 , 数 值 18 的 二 进 制 表 示 是 00000000000000000000000000010010,或者更简洁的 10010。这是 5 个有效位,这 5 位本身就决定了实 际的值

image-20200403180242625

var num = -18
num.toString(2) // "-10010"
  • 按位非(NOT)

按位非操作符由一个波浪线(~)表示, 执行按位非的结果就是返回数值的反码

  • 看不下去了,用到再补内容吧

3.5.3布尔操作符

布尔操作符一共有 3 个:非(NOT)、与(AND)和或(OR)

  • 逻辑非

逻辑非操作符由一个叹号(!)表示,可以应用于 ECMAScript 中的任何值。无论这个值是什么数据 类型,这个操作符都会返回一个布尔值。逻辑非操作符首先会将它的操作数转换为一个布尔值,然后再 对其求反。也就是说,逻辑非操作符遵循下列规则:

  • 如果操作数是一个对象,返回 false;!{}//false
  • 如果操作数是一个空字符串,返回 true;!""//true
  • 如果操作数是一个非空字符串,返回 false; !"1"//false
  • 如果操作数是数值 0,返回 true;!0 //true
  • 如果操作数是任意非 0 数值(包括 Infinity),返回 false;!2 //false !infinity //false
  • 如果操作数是 null,返回 true; !null //true
  • 如果操作数是 NaN,返回 true; !NaN //true
  • 如果操作数是 undefined,返回 true。!undefined //true

双 !! 实际作用与 Boolean() 函数相当

  • 逻辑与(短路操作符)

    逻辑与操作符由两个和号(&&)表示,有两个操作数

    var result = true && false;

    • 如果第一个操作数是对象,则返回第二个操作数
    • 如果第二个操作数是对象, 则只有在第一个操作数的求值结果为 true 的情况下才会返回该 对象
    • 如果两个操作数都是对象,则返回第二个操作数;
    • 如果有一个操作数是 null,则返回 null;
    • 如果有一个操作数是 NaN,则返回 NaN;
    • 如果有一个操作数是 undefined,则返回 undefined。

    逻辑与操作属于短路操作,即如果第一个操作数能够决定结果,那么就不会再对第二个操作数求值。 对于逻辑与操作而言,如果第一个操作数是 false,则无论第二个操作数是什么值,结果都不再可能是 true 了。

    var found = true; 
    var result = (found && someUndefinedVariable); // 这里会发生错误
    alert(result); // 这一行不会执行

    在上面的代码中,当执行逻辑与操作时会发生错误,因为变量 someUndefinedVariable 没有声 明。由于变量 found 的值是 true,所以逻辑与操作符会继续对变量 someUndefinedVariable 求值。 但 someUndefinedVariable 尚未定义,因此就会导致错误。

  • 逻辑或

    逻辑或操作符由两个竖线符号(||)表示,有两个操作数

    var result = true || false;

    • 如果第一个操作数是对象,则返回第一个操作数;
    • 如果第一个操作数的求值结果为 false,则返回第二个操作数
    • 如果两个操作数都是对象,则返回第一个操作数
    • 如果两个操作数都是 null,则返回 null
    • 如果两个操作数都是 NaN,则返回 NaN;
    • 如果两个操作数都是 undefined,则返回 undefined。

    我们可以利用逻辑或的这一行为来避免为变量赋 null 或 undefined 值。

    var a =value1 || value2

    当value1 有值的时候赋值给a,如果value1 为false 则 赋值value2

3.5.4乘性操作符

ECMAScript 定义了 3 个乘性操作符:乘法、除法和求模。这些操作符与 Java、C 或者 Perl 中的相 应操作符用途类似,只不过在操作数为非数值的情况下会执行自动的类型转换。如果参与乘性计算的某 个操作数不是数值,后台会先使用 Number()转型函数将其转换为数值。也就是说,空字符串将被当作 0,布尔值 true 将被当作 1。

  1. 乘法

    var a = 35*20

    • 如果操作数都是数值,执行常规的乘法计算,即两个正数或两个负数相乘的结果还是正数,而 如果只有一个操作数有符号,那么结果就是负数。如果乘积超过了 ECMAScript 数值的表示范围, 则返回 Infinity 或-Infinity;
    • 如果有一个操作数是 NaN,则结果是 NaN;
    • 如果是 Infinity 与 0 相乘,则结果是 NaN;
    • 如果是 Infinity 与非 0 数值相乘,则结果是 Infinity 或-Infinity,取决于有符号操作数 的符号;
    • 如果是 Infinity 与 Infinity 相乘,则结果是 Infinity
    • 如果有一个操作数不是数值, 则在后台调用 Number() 将其转换为数值, 然后再应用上面的 规则
  2. 除法

    • 如果操作数都是数值,执行常规的除法计算,即两个正数或两个负数相除的结果还是正数,而 如果只有一个操作数有符号,那么结果就是负数。如果商超过了 ECMAScript 数值的表示范围, 则返回 Infinity 或-Infinity;

    • 如果有一个操作数是 NaN,则结果是 NaN;

    • 如果是 Infinity 被 Infinity 除,则结果是 NaN

    • 如果是零被零除,则结果是 NaN

    • 如果是非零的有限数除以零,则结果是 Infinity 或-Infinity,取决于有符号操作数的符号

    • 如果是 Infinity 被任何非零数值除,则结果是 Infinity 或-Infinity,取决于有符号操作

    • 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的规则

      Infinity / 9 值为Infinity

      9 / Infinity 值为0

  3. 求模

    求模(余数)操作符由一个百分号(%)表示

    var result = 26 % 5 //1

3.5.5 加性操作符

  1. 加法(➕)

    如果两个操作符都是数值,执行常规的加法计算,然后根据下列规则返回结果:

    • 如果有一个操作数是 NaN,则结果是 NaN
    • 如果是 Infinity 加-Infinity,则结果是 NaN
    • 如果是 Infinity 加 Infinity,则结果是 Infinity
    • 如果是 -Infinity 加 -Infinity,则结果是 -Infinity
    • 如果是+0 加+0,则结果是+0
    • 如果是-0 加-0,则结果是-0
    • 如果是+0 加-0,则结果是+0

    对于字符串来说:

    • 如果两个操作数都是字符串,则将第二个操作数与第一个操作数拼接起来;
    • 如果只有一个操作数是字符串, 则将另一个操作数转换为字符串, 然后再将两个字符串拼接起来

    对于对象、数值、布尔值:

    如果有一个操作数是对象、数值或布尔值,则调用它们的 toString()方法取得相应的字符串值, 然后再应用前面关于字符串的规则。对于 undefined 和 null,则分别调用 String()函数并取得字符 串”undefined”和”null”

    var result = 5 + '5' //55

  2. 减法

    (跳过)

3.5.6 关系操作符

小于(<)、大于(>)、小于等于(<=)和大于等于(>=)这几个关系操作符用于对两个值进行比 较,比较的规则与我们在数学课上所学的一样。这几个操作符都返回一个布尔值

  • 如果两个操作数都是数值,则执行数值比较
  • 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值
  • 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较
  • 如果一个操作数是对象,则调用这个对象的 valueOf()方法,用得到的结果按照前面的规则执 行比较。如果对象没有 valueOf()方法,则调用 toString()方法,并用得到的结果根据前面 的规则执行比较
  • 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较

var result = "Brick" < "alphabet";//true

在这个例子中,字符串”Brick”被认为小于字符串”alphabet”。原因是字母 B 的字符编码为 66, 而字母 a 的字符编码是 97。如果要真正按字母表顺序比较字符串,就必须把两个操作数转换为相同的大 小写形式(全部大写或全部小写),然后再执行比较,

另一种奇怪的现象发生在比较两个数字字符串的情况下:

var result = "23" < "3";

结果为true

这是因为两个操作数都是字符串, 而字符串比较的是字符编码(”2”的字符编码是 50,而”3”的字符编码是 51)

var result = "23" < 3;

结果为false 因为字符串23转换为了数值

var result = 3 > 'a'

结果为false 因为字符串a被转换成了 NaN,任何与NaN作比较都为false

var result = NaN < 3 //false

var result = NaN >= 3 //false

var result = NaN == NaN //false

3.5.7 相等操作符

  1. 相等和不相等

    == != 这两个操作符 都会把值进行强制转换,然后再比较他们的相等性

    遵循以下规则:

    • 如果操作数有布尔值,则转换为数值,false转为0,true转为1

    • 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值

    • 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()方法,用得到的基本类

      型值按照前面的规则进行比较

    • null 和 undefined 是相等的

    • 要比较相等性之前,不能将 null 和 undefined 转换成其他任何值

    • 如果有一个操作数是 NaN,则相等操作符返回 false,而不相等操作符返回 true。重要提示:

      即使两个操作数都是 NaN,相等操作符也返回 false;因为按照规则,NaN 不等于 NaN

    • 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,

      则相等操作符返回 true;否则,返回 false

  2. 全等和不全等

    除了在比较之前不转换操作数之外,全等和不全等操作符与相等和不相等操作符没有什么区别。全 等操作符由 3 个等于号(===)表示,它只在两个操作数未经转换就相等的情况下返回 true

    55 === '55' //false 因为是两个不同类型的值 一个是数值,一个是字符串

    undefined == null // true

    undefined === null //false 因为是不同类型的值,undefined值为undefined,null的值为null

3.5.8 条件操作符

三目运算符

var result = 条件1 ? 答案1 : 答案2

3.5.9 赋值操作符

基础: =

扩展:*= += -= %= /=

3.5.10 逗号操作符

使用逗号操作符可以在一条语句中执行多个操作

var num1=1, num2=2, num3=3;

逗号操作符多用于声明多个变量;但除此之外,逗号操作符还可以用于赋值。在用于赋值时,逗号 操作符总会返回表达式中的最后一项

var num = (5, 1, 4, 8, 0); // num 的值为 0 取最后一项

3.6语句

3.6.1 if语句

if (condition) statement1 else statement2

3.6.2 do-while 语句

do-while 语句是一种后测试循环语句,即只有在循环体中的代码执行之后,才会测试出口条件。 换句话说,在对条件表达式求值之前,循环体内的代码至少会被执行一次。

do {statement} while (expression); //while里面的条件必须为true才能循环

3.6.3 while 语句

while(expression) statement

3.6.4 for 语句

for (initialization; expression; post-loop-expression) statement

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

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

3.6.5 for-in语句

for (property in expression) statement

3.6.6 label 语句

使用 label 语句可以在代码中添加标签,以便将来使用。

label: statement

start: for (var i=0; i < count; i++) { alert(i); }
//这个例子中定义的 start 标签可以在将来由 break 或 continue 语句引用。加标签的语句一般都 要与 for 语句等循环语句配合使用。

let str = "";

loop1:
for (let i = 0; i < 5; i++) {
  if (i === 1) {
    continue loop1;
  }
  str = str + i;
}

console.log(str);
// expected output: "0234"

3.6.7 break和continue语句

break 和 continue 语句用于在循环中精确地控制代码的执行。其中,break 语句会立即退出循环, 强制继续执行循环后面的语句。而 continue 语句虽然也是立即退出循环,但退出循环后会从循环的顶 部继续执行。

break:跳出循环

continue:退出循环,从循环的顶部继续执行

break 和 continue 语句都可以与 label 语句联合使用,从而返回代码中特定的位置。这种联合 使用的情况多发生在循环嵌套的情况下

3.6.8 with语句

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

with (expression) statement;

由于大量使用 with 语句会导致性能下降,同时也会给调试代码造成困难,因此 在开发大型应用程序时,不建议使用 with 语句

3.6.9 switch 语句

var a = 1
switch(a){
  case 1 :
    //do something
    break;
  case 2 :
    //do something 
    break;
};

//合并两种情形
switch(a){
  case 1:
  case 2:
    //命中1或者2时 需要执行的代码
    break;
  default:
    //do something 默认不命中的时候执行
}

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

switch 语句在比较值时使用的是全等操作符,因此不会发生类型转换(例如, 字符串”10”不等于数值 10)

3.7 函数

函数对任何语言来说都是一个核心的概念。通过函数可以封装任意多条语句,而且可以在任何地方、 任何时候调用执行。ECMAScript 中的函数使用 function 关键字来声明,后跟一组参数以及函数体。

function functionName(arg0, arg1,...,argN) { statements }

function name(){
  return //返回一个值
  alert("test") //不会被执行,因为已经有返回值
}
//这个函数会在执行完 return 语句之后停止并立即退出。因此,位于 return 语句之后的任何代码 都永远不会执行。

3.7.1 理解函数

ECMAScript 函数的参数与大多数其他语言中函数的参数有所不同。ECMAScript 函数不介意传递进 来多少个参数,也不在乎传进来参数是什么数据类型。也就是说,即便你定义的函数只接收两个参数, 在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传递参数,而解析器永远不 会有什么怨言。之所以会这样,原因是 ECMAScript 中的参数在内部是用一个数组来表示的。函数接收 到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。如果这个数组中不包含任 何元素,无所谓;如果包含多个元素,也没有问题。实际上,在函数体内可以通过 arguments 对象来 访问这个参数数组,从而获取传递给函数的每一个参数。

关于 arguments 的行为,还有一点比较有意思。那就是它的值永远与对应命名参数的值保持同步。

function doAdd(num1, num2) { arguments[1] = 10; alert(arguments[0] + num2); }

每次执行这个 doAdd()函数都会重写第二个参数,将第二个参数的值修改为 10。因为 arguments 对象中的值会自动反映到对应的命名参数,所以修改 arguments[1],也就修改了 num2,结果它们的 值都会变成 10。不过,这并不是说读取这两个值会访问相同的内存空间;它们的内存空间是独立的,但 它们的值会同步。另外还要记住,如果只传入了一个参数,那么为 arguments[1]设置的值不会反应到 命名参数中。这是因为 arguments 对象的长度是由传入的参数个数决定的,不是由定义函数时的命名 参数的个数决定的。

关于参数还要记住最后一点:没有传递值的命名参数将自动被赋予 undefined 值。这就跟定义了 变量但又没有初始化一样。 例如, 如果只给 doAdd() 函数传递了一个参数, 则 num2 中就会保存 undefined 值。

严格模式对如何使用 arguments 对象做出了一些限制。首先,像前面例子中那样的赋值会变得无 效。 也就是说, 即使把 arguments[1] 设置为 10 , num2 的值仍然还是 undefined 。 其次, 重写 arguments 的值会导致语法错误(代码将不会执行)。

ECMAScript 中的所有参数传递的都是值,不可能通过引用传递参数。

3.7.2 没有重载

ECMAScript 函数不能像传统意义上那样实现重载。而在其他语言(如 Java)中,可以为一个函数 编写两个定义,只要这两个定义的签名(接受的参数的类型和数量)不同即可。如前所述,ECMAScirpt 函数没有签名,因为其参数是由包含零或多个值的数组来表示的。而没有函数签名,真正的重载是不可 能做到的。

如果在 ECMAScript 中定义了两个名字相同的函数,则该名字只属于后定义的函数

function addSomeNumber(num){ return num + 100; }
function addSomeNumber(num) { return num + 200; }
var result = addSomeNumber(100);//300

评论