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

85 阅读24分钟

第三章:基本概念

本章节介绍JavaScript的语法、操作符、数据类型、内置功能等基本概念。

1. 语法

  1. 区分大小写(变量、函数名和操作符都区分大小写)

  2. 标识符

    • 标识符概念: 指变量、函数、属性的名字、或者函数的参数
    • 规则:
      • 第一个字符必须是字母、下划线或$;
      • 其他字符可以是字母、下划线、$或数字。
      • 不能把关键字、保留字、true、false 和 null 用作标识符
    • 建议:采用驼峰命名方式
  3. 注释

    // 单行注释

    /* 这是多行

    注释 */

  4. 严格模式

    // (1) 在js文件顶部加如下代码
      "use strict";
    
    // (2) 指定函数在严格模式下执行
    function doSomething(){ 
     "use strict"; 
      //函数体
    }
    
    // 严格模式下,JavaScript 的执行结果会有很大不同,因此本书将会随时指出严格模式下的区别。
    // 所有现代浏览器 都支持严格模式。
    
  5. 语句

    推荐:以分号结尾

    优点:清晰、避免错误、增进代码性能(解析器不必推测再哪里插入分号)

2. 关键字和保留字

  1. 关键字: 可用于表示控制语句的开始或结束,或者用于执行特定操作等;不能用作标识符

    12345
    breakcasecatchcontinuedefault
    deletedoelsefinallyfor
    functionifininstanceofnew
    returnswitchthisthrowtry
    typeofvarvoidwhilewith
  2. 保留字:以下是 ECMA-262 第 6 版为将来保留的所有词汇。

    始终保留:enum

    严格模式下保留:

    implements  package     public
    interface   protected   static
    let         private
    

    模块代码中保留: await

3. 变量

​ ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。

var关键字

使用

// 基本使用
var a = "hello"; 

 // 1. 声明未定义  为 undefined
var msg; 

// 2. 可以重新赋值为其他类型值
var message = "hi"; 
message = 100; 

// 3.如果需要定义多个变量,可以在一条语句中用逗号分隔每个变量(及可选的初始化):
var message = "hi",
    found = false,
    age = 29;

作用域

  • 全局变量:在全局作用域下声明的变量

    <script>
      // 全局变量a
      var a = 100;
    
      // 全局变量b
      function fun() {
         b = 100; // 省略了var操作符  则为全局变量 (特殊情况下的全局变量 不推荐)
      }
    </script>
    
  • 局部变量: 在局部作用域下声明的变量,比如函数内声明的变量。

     <script>
        function fun() {
           var b = 100; 
        }
    </script>
    

var声明提升

WX20240830-153007@2x.png

4. 数据类型

数据类型分为:

  • 基本数据类型:Number、 String、Boolean、Null、Undefined、Symbol(ES6加入)
  • 复杂数据类型:Object

4.1 基本数据类型

4.1.1 Number
  • 数值表示

    使用IEEE754格式来表示整数和浮点数值(即双精度值);可以使用十进制、八进制、十六进制表示

    var intNum = 55; // 十进制 整数55
    var octalNum1 = 070; // 八进制的 56
    var hexNum1 = 0xA; // 十六进制的 10
    // 计算时都会被转为十进制
    
  • 浮点数值:

    须包含一个小数点,并且小数点后面必须至少有一位数字,如:var a = 10.2;

    对于那些极大或极小的数值,可以用e表示法(即科学计数法)表示的浮点数值表示:

    var floatNum = 3.125e7; // 等于 31250000
    // 如 0.00000000000000003,这个数值可以使用更简洁的 3e-17表示浮点数值的最高精度是 17 位小数.
    
  • 0.1 + 0.2 == 0.3 // false why?

    原因:浮点数运算过程,将十进制转为二进制,按照小数转换规则,0.1转为无限循环数, IEEE 754 标准的 64 位双精度浮点数的小数部分最多支持 53 位二进制位,所以两者相加后不等于0.3

  • 数值范围

    最小数值:Number.MIN_VALUE (-Infinity ) 在大多数浏览器中,这个值是 5e-324

    最大数值:Number.MAX_VALUE (Infinity ) 在大多数浏览器中,这个值是 1.7976931348623157e+308

    超过该范围,则为 Infinity 。

    判断一个数值是不是有穷的:使用isFinite()函数

  • NaN

    非数值(Not a Number)是一个特殊的数值

    NaN与任何值都不相等,包括NaN本身:NaN == NaN //false

    判断是不是NaN, 使用isNaN(), isNaN会把参数转为数值类型后判断

    尽管有点儿不可思议,但 isNaN() 确实也适用于对象。在基于对象调用isNaN()函数时,会首先调用对象的valueOf()方法,然后确定该方法返回的值是否可以转换为数值。如果不能,则基于这个返回值再调用toString()方法,再测试返回值。而这个过程也是ECMAScript中内置函数和操作符的一般执行流程,更详细的内容请参见 3.5 节。

  • 数值转换

    • Number()可以用于任何数据类型

      boolean  true -> 1 false -> 0
      undefined -> NaN
      null -> 0
      number ->转为十进制输出
      string规则:
          只包含数字
            Number('10')  ->  10
            Number('012') ->  12 (前面的0忽略)
          含有效的浮点格式(前后多余0都忽略)
            Number('01.2') -> 1.2   
            Number('1.20') -> 1.2 
          十六进制格式,转换为相同大小的十进制整数值;
          字符串是空的:转换为 0; 
          如果包含除上述格式之外的字符(abc...@!$%...),则将其转换为 NaN。
      对象规则:
         如果是对象,则调用对象的 valueOf()方法,然后依照前面的规则转换返回的值。如果转换的结果是 NaN,则调用对象的 toString()方法,然后再次依照前面的规则转换返回的字符串值。
      
    • parseInt()专门用于把字符串转换成数值,支持参数2

      parseInt('1') // 1
      parseInt('01') // 1
      parseInt('01x') // 1
      parseInt('x01') // NaN
      parseInt('') // NaN
      parseInt(' ') // NaN
      parseInt(true) // NaN
      parseInt(null)// NaN
      parseInt(undefined)// NaN
      // 在使用 parseInt()解析像八进制字面量的字符串时,ECMAScript 3 和 5 存在分歧。例如:ECMAScript 3 认为是 56(八进制),ECMAScript 5 认为是 70(十进制)
      var num = parseInt("070");
      // 为避免这种错误,parseInt('070', 10)支持传入第二个参数,为输出的进制类型
      var num1 = parseInt("10", 2); //2 (按二进制解析)
      var num2 = parseInt("10", 8); //8 (按八进制解析)
      var num3 = parseInt("10", 10); //10 (按十进制解析)
      var num4 = parseInt("10", 16); //16 (按十六进制解析)
      
    • parseFloat()专门用于把字符串转换成数值,只解析十进制值

      var num1 = parseFloat("1234blue"); //1234 (整数)
      var num2 = parseFloat("0xA"); //0 
      var num3 = parseFloat("22.5"); //22.5 
      var num4 = parseFloat("22.34.5"); //22.34 
      var num5 = parseFloat("0908.5"); //908.5 
      var num6 = parseFloat("3.125e7"); //31250000
      
4.1.2 String
  • 创建:双引号、单引号;

    var firstName = "Nicholas";

    var lastName = 'Zakas';

    特殊字符:\n 换行;\t 制表;\b 空格;'; ";...

    使用length访问长度;

    字符串是不可变的,要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量。

  • 字符串转换

    • toString()

      null 和 undefined 值没有这个方法

      可传参,参数为输出数值的基数(多少进制)

      var age = 11; 
      var ageAsString = age.toString(); // 字符串"11" 
      var found = true; 
      var foundAsString = found.toString(); // 字符串"true"
      [].toString(); // ""
      [1,2,3].toString(); //1,2,3
      var obj = {}; obj.toString(); // "[object Object]"
      
    • String()任何类型的值转换为字符串

      • 如果值有 toString()方法,则调用该方法(没有参数)并返回相应的结果;
      • 如果值是 null,则返回"null";
      • 如果值是 undefined,则返回"undefined"。
4.1.3 Boolean
  • 该类型只有两个字面值:true 和 false
  • 转换为boolean类型:Boolean();
  • 转为false的情况: ""、false、0/NaN、null、undefined; 其余情况为true;
4.1.4 Null

null 值表示一个空对象指针;

4.1.5 Undefined
  1. 变量声明未赋值;
  2. 访问对象没有赋值的属性;
  3. 函数需要实参,但是未传值,形参是undefined;
  4. 函数调用没有返回值或者return后没有数据,接收函数返回的变量是undefined。

null 和 undefined

undefined == null //返回true undefined === null //返回false

Number(null) // 0; Number(undefined) // NaN

4.2 复杂数据类型(引用类型)Object

  • 创建实例: var obj = new Object();

    要理解一个重要的思想:即在ECMAScript中,Object类型是所有它的实例的基础。换句话说, Object类型所具有的任何属性和方法也同样存在于更具体的对象中。Object 的每个实例都具有下列属性和方法。

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

WX20240925-091905@2x.png

WX20240830-162731@2x.png

4.3 数据类型检测

typeof

  1. 检测基本数据类型: 除了null以外都能返回正常的值 如:typeof 1 返回为'number';(typeof NaN 返回‘number’) typeof null --> 'object';
  2. 检测引用类型: 除function外都返回'object' typeof Function --> 'function'

详细的数据类型检测介绍及实用场景

5. 操作符

5.1 一元操作符(++,--或者+,-)
  1. 递增和递减操作符
  • 前置:++(--)值先递增(递减),后执行语句;

  • 后置:值++(--)先使用值执行语句,后递增(递减)

  • 这四个操作符对任何值都适用,不仅适用与整数,还可用于字符串、布尔值、浮点数值和对象

  • 应用于不同的值时,遵循下列规则

    • 在应用于一个包含有效数字的字符串时,先将其转化为数字值,再执行加减1的操
    • 在应用一个不包含有效数字的字符串时,将变量的值设为NaN
    • 在应用于布尔值时,先将其转换为数值变量,再执行j加减1的操作
    • 在应用于浮点数值时,执行加减1的操作
    • 在应用于对象时,先调用对象的 valueOf()方法(第 5 章将详细讨论)以取得一个可供操作的值。然后对该值应用前述规则。如果结果是 NaN,则在调用 toString()方法后再应用前述规则。对象变量变成数值变量。
    var num1 = 2; 
    var num2 = 20; 
    var num3 = --num1 + num2; // 等于 21 
    var num4 = num1 + num2; // 等于 21
    
    var num1 = 2; 
    var num2 = 20; 
    var num3 = num1-- + num2; // 等于 22 
    var num4 = num1 + num2; // 等于 21
    
  1. 一元加和减操作符

    • 一元加操作符(+) 放在前面
      • 数值时:不会产生任何影响
      • 用于非数值时:该操作符会像Number()转型函数一样对这个值执行转换
      • 布尔值:会转换成0和1
      • 字符串值:会按照一组特殊的规则进行解析,
      • 对象:是先调用它们的valueOf()和(或)toString()方法,在转换得到的值。
    • 一元减操作符(-)主要用于表示负数
      • 数值时,表示负数
      • 非数值时,一元减操作符与一元加操作符相同的规则,最后在将得到的数值转换为负数
    var s1="01";
    var s2="1.1";
    var s3="z";
    var b=false;
    var f=1.1;
    var 0={
    	valueOf:function(){
    		return -1;
    	}
    };
    
    s1=-s1;//-1
    s2=-s2;//-1.1
    s3=-s3;//NaN
    b=-b;//0
    f=-f;//-1.1
    0=-0;//1
    
5.2 位操作符

位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值。ECMAScript 中的所有数值都以 IEEE-754 64 位格式存储,但位操作符并不直接操作 64 位的值。而是先将 64 位的值转换成 32 位的整数,然后执行操作,最后再将结果转换回 64 位。

  • 按位非(NOT) 按位操作符(~),执行按位非的结果就是返回数值的反码 按位非操作的本质:操作数的负值减1

  • 按位与(AND) 按位与操作符(&),它有两个操作数 按位与操作只有在两个数值的对应位都是1时才返回1,任何一位是0,结果都是0

  • 按位或(OR) 按位或操作符(|),它有两个操作数 按位或操作在有一位是1的情况下就返回1,而只有在两个位都是0的情况下才返回0

  • 按位异或(XOR) 按位异或符(^),它有两个操作数 两个数值对应位值不同,则返回1;否则返回0

  • 左移 左移操作符(<<),这个操作符会将数值的所有位向左移动指定的位数 左移操作后,会以0来填充右侧的空位 左移不会影响操作数的符号位

  • 有符号的右移 有符号的右移操作符(>>),这个操作符会将数值向右移动,但保留符号位 有符号的右移操作与左移操作正好相反 向右移位后,将出现在原数值的左侧、符号位的右侧的空位,用符号为的值来填充

  • 无符号右移 无符号右移操作(>>>),这个操作符会将数值的32位都向右移动 对正数来说,无符号右移的结果与有符号右移相同 对负数来说

    无符号右移是0来填充空位,而不是向有符号右移那样以符号位的值来填充空位 对正数的无符号右移与有符号右移结果相同,但对负数的结果就不一样了 无符号右移操作符会把负数的二进制码当成正数的二进制码 由于负数以其绝对值的二进制补码来表示,因此会导致无符号右移后的结果非常大

5.3 布尔操作符(!/&/||)
  • 逻辑非(!)
    • 操作数是一个对象,则返回false、
    • 操作数是一个空字符串,返回true
    • 操作符是一个非空字符串,返回flase
    • 操作数是数值0,返回true
    • 操作数是任意非0数值(包括Infinity),返回false
    • 操作数是null,返回true
    • 操作数是NaN,返回true
    • 操作数是undefined,返回true
  • 逻辑与(&)--短路操作符 不能在逻辑与操作中使用未定义的值
    • 如果第一个操作数为true,则返回第二个操作数
    • 如果第二个操作数为false,则返回第一个操作数
  • 逻辑或(||)--短路操作符 不能在逻辑与操作中使用未定义的值
    • 如果第一个操作数为true,则返回第一个操作数
    • 如果第一个操作数为false,则返回第二个操作数
5.4 乘性操作符(*或者/或者%)
  • 乘法(*)

    如果参与乘性计算的某个操作数不是数值,后台会先使用Number()转型函数将其转换为数值。

    在处理特殊值的情况下,乘法操作符遵循下列特殊的规则:

    • 如果乘积超过了 ECMAScript 数值的表示范围,则返回 Infinity 或-Infinity;
    • 如果有一个操作数是 NaN,则结果是 NaN;
    • 如果是 Infinity * 0 ,则结果是 NaN;
    • 如果是 Infinity 与非 0 数值相乘,则结果是 Infinity 或-Infinity,取决于有符号操作数的符号;
    • 如果是 Infinity * Infinity ,则结果是 Infinity;
    • 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的规则。
  • 除法(/)

    • 如果商超过了JavaScript数值的表示范围,则返回Infinity或-Infinity
    • 如果一个操作数是NaN,则结果是NaN
    • 如果是Infinity/Infinity除,则结果是NaN
    • 如果是0/0,则结果是NaN
    • 如果是非零的有限数被零除,则结果是Infinity或-Infinity,取决于有符号操作数的符号
    • 如果是Infinity被任何非零数值除,则结果是Infinity或-Infinity,取决于有符号操作数的符号
    • 如果有一个操作数不是数值,则在后台调用Number()将其转换为数值,然后应用上面的规则
  • 求模(%)余数 (被除数/除数 = 商...余数)

    • 如果操作数都是数值,执行常规的除法计算,返回除得的余数
    • 如果被除数是无穷大值而除数是有限大的数值,则结果是 NaN
    • 如果被除数是有限大的数值而除数是零,则结果是 NaN
    • 如果是 Infinity % Infinity ,则结果是 NaN
    • 如果被除数是有限大的数值而除数是无穷大的数值,则结果是被除数
    • 如果被除数是零,则结果是零
    • 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的规则
5.5 加性操作符(+或者-)
  • 加法+

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

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

    如果有一个操作数是字符串,那么就要应用如下规则:

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

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

  • 减法-

    • 如果两个操作符都是数值,则执行常规的算术减法操作并返回结果;
    • 如果有一个操作数是 NaN,则结果是 NaN;
    • 如果是 Infinity - Infinity,则结果是 NaN;
    • 如果是-Infinity -(-Infinity),则结果是 NaN;
    • 如果是 Infinity -(-Infinity),则结果是 Infinity;
    • 如果是-Infinity - Infinity,则结果是-Infinity;
    • 如果是+0 减+0,则结果是+0;
    • 如果是+0 减-0,则结果是-0;
    • 如果是-0 减-0,则结果是+0;
    • 如果有一个操作数是字符串、布尔值、null 或 undefined,则先在后台调用 Number()函数将其转换为数值,然后再根据前面的规则执行减法计算。如果转换的结果是 NaN,则减法的结果就是 NaN;
    • 如果有一个操作数是对象,则调用对象的 valueOf()方法以取得表示该对象的数值。如果得到的值是 NaN,则减法的结果就是 NaN。如果对象没有 valueOf()方法,则调用其 toString()方法并将得到的字符串转换为数值。
5.6 关系操作符(< > <= >=)
  • 小于(<)、大于(>)、小于等于(<=)和大于等于(>=)这几个关系操作符用于对两个值进行比较。这几个操作符都返回一个布尔值
  • 规则
    • 如果这两个操作数都是数值,则执行数值比较
    • 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值
    • 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较
    • 如果一个操作数是对象,则调用这个对象的valueOf()方法,并用得到的结果根据前面的规则执行比较
    • 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较
5.7 相等操作符(== != === !==)
  • 相等(==)和不相等(!=) 都会先转换操作数(强制转型),然后再比较它们的相等性。 转换不同经数据类型时,遵循下列规则:

    • 如果一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false转换 为0,true转换为1
    • 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值
    • 如果一个操作数是对象,另一个操作数不是,则调用对象的valueOf()方法,用得到的基本类型值按照前面的规则进行比较

    这两个操作符进行比较时,遵循下列规则:

    • null和undefined是相等的
    • 要比较相等性之前,不能将null和undefined转换成其它任何值
    • 如果一个操作数是NaN,则相等操作符返回false,而不相等操作符返回true(即使两个操作数都是NaN,相等操作符返回false,因为按照规则,NaN不等于NaN)
    • 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,则相等操作符返回true;否则,返回false
  • 全等(===)和不全等(!==)

    不进行类型转换,直接比较

5.8 条件操作符(三元运算符

var max = (num1 > num2) ? num1 : num2; // max 中将会保存一个最大的值

5.9 赋值操作符(= += *=...)
  • 赋值操作符(=),将右侧的值赋给左侧的变量
  • 复合赋值
    • 乘赋值:*=
    • 除赋值:/=
    • 模)赋值:%=
    • 加赋值:+=
    • 减赋值:-=
    • 左移:<<=
    • 有符号右移赋值:>>=
    • 无符号右移赋值:>>>=
5.10 逗号操作符(,)

可以在一条语句中执行多个操作,多用于声明多个变量: var num1=1, num2=2, num3=3;

在用于赋值时,逗号操作符总会返回表达式中的最后一项: var num = (5, 1, 4, 8, 0); // num 的值为0 ,由于 0是表达式中的最后一项,因此num的值就是0

6.语句

if语句

()中的条件可以是任意表达式,表达式结果如果不是布尔值,会调用Boolean()转换函数将这个表达式的结果转换为一个布尔值

if (i > 25) 
 alert("Greater than 25."); // 单行语句
else { 
 alert("Less than or equal to 25."); // 代码块中的语句
}

do-while语句

一种后测试循环语句,即只有在循环体中的代码块执行之后,才会测试出口条件

最常用于循环体中的代码至少要被执行一次的情形。

// 下面是一个示例:
var i = 0; 
do { 
 i += 2; 
} while (i < 10);
alert(i); // 10

while语句

前测试循环语句,在循环体内的代码被执行之前,就会对出口条件求值。

var i=0;
while(i<10){
	i += 2;
}
//变量i开始时的值为0,每次循环都会递增2。只要i的值小于10,循环就会一直执行下去

for语句

前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行的代码的能力.

var count = 10; 
for (var i = 0; i < count; i++){ 
 alert(i); 
}
// 有必要指出的是,在 for 循环的变量初始化表达式中,也可以不使用 var 关键字。该变量的初始化可以在外部执行,例如:
var count = 10; 
var i; 
for (i = 0; i < count; i++){ 
 alert(i); 
}
alert(i); // 10
// 以上代码与在循环初始化表达式中声明变量的效果是一样的。由于 ECMAScript 中不存在块级作用域(第 4 章将进一步讨论这一点),因此在循环内部定义的变量也可以在外部访问到。

// for 语句中的初始化表达式、控制表达式和循环后表达式都是可选的。将这三个表达式全部省略,就会创建一个无限循环,例如:
for (;;) { // 无限循环
 doSomething(); 
} 
// 而只给出控制表达式实际上就把 for 循环转换成了 while 循环,例如:
var count = 10; 
var i = 0; 
for (; i < count; ){ 
 alert(i); 
 i++; 
}

for-in语句

是一种精准的迭代语句,可以用来枚举对象的属性;

通过 for-in 循环输出的属性名的顺序是不可预测的

如果表示要迭代的对象的变量值为nullundefinedfor-in语句会抛出错误。ECMAScript5:对这种情况不抛出错误,而是不执行循环体。

for (var propName in window) { 
 console.log(propName); 
}

label语句

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

break和continue语句

break 和 continue 语句用于在循环中精确地控制代码的执行。

break 语句: 会立即退出循环,强制继续执行循环后面的语句

continue 语句: 虽然也是立即退出循环,但退出循环后会从循环的顶部继续执行

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

// break 和 continue 语句都可以与 label 语句联合使用,从而返回代码中特定的位置。这种联合使用的情况多发生在循环嵌套的情况下,如下面的例子所示:
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; 
 } 
 num++; 
 } 
} 
alert(num); //55
var num = 0; 
for (var i=1; i < 10; i++) { 
 if (i % 5 == 0) { 
    continue; 
 } 
 num++; 
} 
alert(num); //8

with语句

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

with(location){
	var qs=search.substring(1);
	var hostNmae=hostname;
	var url=href;
}
//使用with语句关联了location对象。在with语句的代码块内部,每个变量首先被认为是一个局部变量,如果在局部变量的内部找不到该变量的定义,就会查询location对象中是否有同名的属性。如果发现了同名的属性,则以location对象属性的值作为变量的值

严格模式下不循序使用with语句,否则将视为语法错误;

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

switch语句

case的含义是:“如果表达式等于这个值(value),则执行后面的语句(statement)”。

break 关键字会导致代码执行流跳出 switch 语句。如果省略 break 关键字,就会导致执行完当前 case 后,继续执行下一个 case。

最后的 default 关键字则用于在表达式不匹配前面任何一种情形的时候,执行机动代码(因此,也相当于一个 else 语句)。

比较值时使用的是全等操作符,因此不会发生类型转换

switch (i) { 
 case 25: 
   /* 合并两种情形 */
 case 35: 
   alert("35"); 
   break; 
 case 45: 
   alert("45"); 
   break; 
 default: 
   alert("Other"); 
}
// 每个 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."); 
}

7.函数

在第5章及第七章中,有函数相关内容的详细介绍,本章内容如下:

  • 函数声明

    function sayHi(name, message) { 
     alert("Hello " + name + "," + message); 
    }
    
  • 函数调用

    使用函数名调用,加上一对圆括号和参数

    sayHi("Nicholas", "how are you today?");

  • 函数返回值

    返回值可以有 可以没有, 没有则是undefined;

    有的情况,使用return 返回;return后面任何代码不会执行;return 也可以不带有任何返回值,这种情况是undefined

    function sayHi(name, message) { 
     return; 
     alert("Hello " + name + "," + message); //永远不会调用
    }
    

    推荐的做法是要么让函数始终都返回一个值,要么永远都不要返回值。否则,如果函数有时候返回值,有时候有不返回值,会给调试代码带来不便。

    严格模式对函数有一些限制:

    • 不能把函数命名为 eval 或 arguments;
    • 不能把参数命名为 eval 或 arguments;
    • 不能出现两个命名参数同名的情况。
  • 函数参数

    • 函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型
    • 函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给函数的每一个参数
    • arguments 是类数组 可以arguments[i] arguments.length
    • 命名的参数只提供便利,但不是必需的
    • arguments对象可以与命名参数一起使用
    • arguments它的值永远与对应命名参数的值保持同步, 它们的内存空间是独立的,但它们的值会同步
    • 如果只传入了一个参数,那么为 arguments[1]设置的值不会反应到命名参数中。这是因为 arguments 对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。
    • 没有传递值的命名参数将自动被赋予 undefined 值
  • 没有重载

    ECMAScript中也没有函数签名的概念,因为其函数参数是以一个包含零或多个值的数组的形式传递的。

    如果在ECMAScript中定义了两个名字相同的函数,后者会覆盖前者。

[相关内容]

  • [1] 著者.JavaScript高级程序设计[M].人民邮电出版社,(美)泽卡斯(ZAkas,N.C.) , 李松峰,曹力 译,2012.3