二、JavaScript 基本语法

1、标识符

标识符是指变量、函数、属性的名字,或函数的参数。

格式规则:

  • 第一个字符必须是一个字母、下划线(_)或一个美元符号($)。
  • 其他字符可以是字母、下划线、美元符号或数字。
  • 不能把关键字、保留字、true、false、和 null 用作标识符。
  • 最好采用驼峰大小写格式。

2、关键字

关键字用途:

  • 用于表示控制语句的开始或结束。
  • 用于执行特定操作等。

关键字举例

break           do             instanceof       typeof  
case            else           new              var  
catch           finally        return           void  
continue        for            switch           while  
debugger*       function       this             with  
default         if             throw            let
delete          in             try              yield

3、变量

  ECMAScript 的变量时松散类型的,所谓松散类型就是可以用来保存任何类型的数据。
  初始化变量:给变量赋值。

可以在修改量值的同时修改值的类型,但不推荐。

4、数据类型

5 种简单数据类型(基本数据类型):

  • Undefined — undefined
  • Null — null
  • Boolean — true ,false
  • Number
  • String

1 种复杂数据类型 —— Object:本质上是由一组无序的名值对组成的。

4.1、typeof 操作符

  因为 ECMAScript 是松散类型的,所以需要一种手段来检测给定变量的数据类型 —— typeof就是用来检测变量数据类型的操作符。

typeof 操作符的返回值:

  • "undefined" —— 这个值未定义
  • "boolean" —— 是布尔值
  • "string" —— 是字符串
  • "number" —— 是数值
  • "object" —— 是对象或 null
  • "function" —— 是函数

用法:

var message = " some string";
typeof message;    // "string"
typeof(message);   // "string"

注意:typeof 是操作符而不是函数,因此圆括号可以使用,但不是必需。

4.2、undefined 类型

  undefined 类型只有一个值,即 undefined。使用 var 声明变量但未初始化时,这个变量的值就是 undefined。
  包含 undefined 值的变量与尚未定义的变量是不一样的。例:

var message;  // 变量声明后默认取得了 undefined 值
// 下面这个变量并没有声明
// var age

console.log(message);   // "undefined"
console.log(age);      // 产生错误:Uncaught ReferenceError: age is not defined  

  对未初始化的变量执行 typeof 操作符会返回 undefined 值,对未声明的变量执行 typeof 操作符同样会返回 undefined 值。例子:

var message;  // 变量声明后默认取得了 undefined 值
// 下面这个变量并没有声明
// var age

console.log(typeof message);   // "undefined"
console.log(typeof age);       // "undefined"

建议:显示地初始化变量。如果这样做,那么当 typeof 操作符返回 "undefined" 值时,就能知道被监测的变量还没有被声明,而不是尚未初始化。

4.3 Null 类型

  Null 类型是第二个只有一个值的数据类型,这个特殊的值是 null 。 从逻辑角度看, null 值表示一个空对象指针。例:

var  a  = null;
console.log(typeof a);    // "object"

建议:如果定义的变量准备用于保存对象,最好将该变量初始化为 null 。这样只要直接检查 null 的值就可以知道相应的变量是否已经保存了一个对象的引用。例:
if (a != null) {// 对 a 对象执行某些操作}

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

console.log(null == undefined);  // true

  尽管 null 和 undefined 有这样的关系,但它们的用途完全不同。无论在什么情况下都没有必要吧一个变量的值显示地设置为 undefined,可是同样的规则对 null 不适用。只要意在保存对象的变量还没有真正的保存对象,就应该明确的让该变量保存 null 值。这样不仅可以体现 null 作为空对象指针的惯例,而且也有助于进一步区分 null 和 undefined。

4.4 Boolean 类型

  Boolean 类型是 ECMAScript 中使用最多的一种类型,该类型只有两个字面值: true 和 false。

注意:Boolean 类型的字面值 true 和 false 是区分大小写的。也就是说,True 和 False (以及其他的混合大小写形式)都不是 Boolean 值,只是标识符。

  虽然 Boolean 类型的字面值只有两个,但 ECMAScript 中所有类型的值都有与这两个 Boolean 值等价的值。可以调用转型函数 Boolean() 将一个值转换为其对应的 Boolean 值。

数据类型 转换为 true 的值 转换为 false 的值
Boolean true false
Undefined n/a undefined
String 任何非空字符串 " " (空字符串)
Number 任何非零数字值(包括无穷大) 0 和 NaN
Object 任何对象 null

n/a(或 N/A),是 not applicable 的缩写,意思是 “不适用”。

4.5、Number 类型

数字字面量格式

  • 十进制整数 — 最基本的数值字面量格式。
  • 八进制整数 — 第一位必须是零(0),然后是八进制数字序列(0~7),如果字面值中的数值超出范围,那么前导零将被忽略,后面的数值将被当作十进制数值解析。严格模式下八进制字面量无效,会导致支持的JavaScript引擎抛出错误
var octalNum1 = 070;  // 八进制的56
var octalNum2 = 079; // 无效的八进制数值—解析为79
var octalNum3 = 08;  // 无效的八进制数值—解析为8
  • 十六进制整数 — 前两位必须是0x,后跟任何十六进制数字(0 ~ 9 及 A ~ F),字母可以大写,也可以小写。
var hexNum1 = 0xA;  //  十六进制的 10
var hexNum2 = 0x1f;    // 十六进制的 31 

在进行算数计算时,所有以八进制和十六进制表示的数值都将被转换成十进制数值。

4.5.1、 浮点数值

浮点数值 — 该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。

小数点前面可以没有整数,但不建议这样写

4.5.2、 数值范围

ECMAScript能够表示的数值(大多数浏览器中):

  • 最小数值保存在 Number.MIN_VALUE 中 — 5e-324。
  • 最大数值保存在 Number.MAX_VALUE 中 — 1.7976931348623157e+308。
    超出范围后,这个数值被自动转换成 Infinity(无穷数)。

确定一个数值是不是有穷的,使用 isFinite() 函数,有穷返回 true

4.5.3、NaN

  NaN, 非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会抛出错误, 从而影响其他代码的执行)。

NaN 本身有两个非同寻常的特点:

  • 任何涉及 NaN 的操作都会返回 NaN。
  • NaN 与任何值都不相等,包括 NaN 本身。
  • 只有 0 除以 0 才会返回NaN, 整数除以 0 返回 Infinity,负数除以 0 返回 -Infinity。

  isNaN() 函数,可以判断一个值是否“不是数值”,,任何不能被转换为数值的值都会导致这个函数返回 true。

4.5.4、数值转换

将非数值转换成数值:

  • Number() 可用于任何函数。
  • parseInt()、parseFloat() 只用于将字符串转换为数值。

Number() 函数的转换规则:

  • Boolean — true 和 false 分别被转换为 1 和 0
  • 数字值 — 只是简单的传入和返回
  • null — 返回 0
  • undefined — 返回 NaN
  • 字符串 —
    • 如果字符串中只包含数字 — 将其转换成十进制数值。
    • 如果字符串中含有有效的浮点格式 — 将其转换为对应的浮点数值。
    • 如果字符串中含有有效的十六进制格式 — 将其转换为相同大小的十进制整数值。
    • 如果字符串是空的 — 将其转换为 0。
    • 如果字符串包含除上述格式之外的字符 — 将其转换为 NaN。
  • 如果是对象 — 调用对象的 valueOf() 方法,然后依照前面的规则转换返回的值;如果转换的结果是 NaN ,则调用对象的 toString() 方法,然后在按照前面的规则转换返回的字符串值。
var num1 = Number("Hello world!");  // NaN
var num2 = Number(" ");             // 0
var num3 = Number("000011");        // 11
var num4 = Number(true);            // 1

一元加操作符的操作与 Number() 函数相同

  由于 Number() 函数在转换字符串是比较复杂而且不够合理,因此在处理整数时更常用的是 parseInt() 函数。
  parseInt() 函数在使用时应始终指定基数。
  parseFloat() 函数只解析十进制数值。

4.6、String 类型

  String 类型用于表示由零或多个 16 位 Unicode 字符组成的字符序列,即字符串。字符串可以由双引号(")或单引号(')表示,这两种写法都是有效的,但前后必须一致。

4.6.1、字符字面量

  String 数据类型包含一些特殊的字符字面量,也叫转义序列,用于表示被打印字符,或者具有其他用途的字符:

字面量 含义
\n 换行
\t 制表
\b 空格
\r 回车
\f 进纸
\ 斜杠
' 单引号(')
" 双引号(")
4.6.2、字符串的特点

  ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后在用另一个包含新值的字符串填充该变量。这个过程是在后台发生的,而这也是在某些旧版本的浏览器(如版本低于1.0的FIrefox、IE6等)中拼接字符串时速度很慢的原因所在。但在这些浏览器后来的版本已经解决了这个低效率的问题。

4.6.3、转换为字符串

两种方法:

  • toString() 方法,除 null 和 undefined 值都有这个方法。调用数值的 toString() 方法时,可以传递一个参数:输出数值的基数。默认情况下,toString() 方法以十进制格式返回数值的字符串表示,而通过传递基数,toString() 可以输出以二进制、八进制、十六进制,乃至其他任意有效进制格式表示的字符串值。
  • String() 方法,将任何值转换为字符串。null 值返回"null", undefined 返回 "undefined"。

使用:

var num = 10;
var n = null;
var boolean  = true;
// toString()
num.toString();        // "10"
num.toString(2);       // "1010"
boolean  .toString();  // "true"
num.toString(n);       // 报错
// String 
String(num);          // "10"
String(n);            // "null"
String(boolean  );    // "true"

将某个值转换为字符串:num + " ";

4.7、Object类型

  ECMAScript 中的对象是一组数据和功能的集合。创建 Object 类型的实例并为其添加属性和(或)方法,就可以创建自定义对象。

var o = new Object();

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

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

5、 操作符

5.1、一元操作符

只能操作一个值的操作符叫做一元操作符

5.1.1、递增和递减操作符
var age = 0;
  • 前置递增 —— ++age; // 1
  • 前置递减 —— --age; // -1
  • 后置递增 —— age++; // 1
  • 后置递减 —— age--; // -1

递增和递减操作符作用于其它数据类型的值时:

  • 包含有效数字字符的字符串,先将其转为数字值,再执行加减 1 的操作,字符串变量变成数值变量。
  • 不包含有效数字字符的字符串,将变量的值设置为 NaN,字符串变量变成数值变量。
  • 布尔值 false,先转换为 0 再执行加减 1 的操作,布尔值变量变为数值变量。
  • 布尔值 true ,先转换为 1 再执行加减 1 的操作,布尔值变量转为数值变量。
  • 浮点数值,执行加减 1 的操作。
  • 对象,先调用对象的 valueOf() 方法取得一个可供操作的值,应用上述规则。
5.1.2、一元加和减操作符

一元加操作符以一个加号(+)表示,对数值不会产生影响

var num = 0;
num = +num;  //  仍然是 0

  对非数值应用一元加操作符时,该操作符回像 Number() 转型函数一样对这个值进行转换。
  一元减操作符用于数值时,该值变为负数,用于非数值时,同一元加操作符规则相同,再将得到的数值转为负数。

var b = false;   // 0

5.2、位操作符(待定)

位操作符用于在最基本的层次上,即按内存中表示数值的位来操作数值。

5.3、布尔操作符

布尔操作符共有 3 个:

  • 非(NOT)
  • 与(AND)
  • 或(OR)
5.3.1、逻辑非

  逻辑非操作符由一个叹号(!)表示,可以应用与ECMAScript中的任何值。无论这个值是什么数据类型,这个操作符都会返回一个布尔值。逻辑非操作符会先将它的操作数转换为一个布尔值,再对其求反。

逻辑非操作符遵循规则:

  • 对象 —— false
  • 空字符串 —— true
  • 非空字符串 —— false
  • 数值 0 —— true
  • 非 0 数值(包括Infinity) —— false
  • null —— true
  • NaN —— true
  • undefined —— true

同时使用两个逻辑非操作符(!!)将一个值转换为布尔值,同 Boolean() 函数相同。

5.3.2、逻辑与

逻辑与操作符由两个和号(&&)表示,有两个操作数。
逻辑与的真值表:

第一个操作数 第二个操作数 结果
true true true
true false false
false true false
false false false

  逻辑与操作可以应用于任何类型的操作数。在有一个操作数不是布尔值的情况下,逻辑与操作不一定返回布尔值,遵循规则:

  • 第一个操作数是对象,返回第二个操作数
  • 第二个操作数是对象,只有第一个操作数的求值结果为 true 的情况下才会返回该对象
  • 两个操作数都是对象,返回第二个操作数
  • 有一个操作数是 null,返回 null
  • 有一个操作数是 NaN, 返回 NaN
  • 有一个操作数是 undefined, 返回 undefined
  • 同时有 null、NaN 或 undefined,返回第一个对象

  逻辑与操作属于短路操作,即如果第一个操作数能够决定结果,就不会再对第二个操作数求值。

5.3.3、逻辑或

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

var result = true || false;

逻辑或的真值表:

第一个操作数 第二个操作数 结果
true true true
true false true
false true true
false false false

  逻辑或操作可以应用于任何类型的操作数。在有一个操作数不是布尔值的情况下,逻辑或操作不一定返回布尔值,遵循规则:

  • 第一个操作数是对象,返回第一个操作数
  • 第一个操作数的求值结果为false,返回第二个操作数
  • 两个操作数都是对象,返回第一个操作数
  • 两个操作数是 null,返回 null
  • 两个操作数是 NaN, 返回 NaN
  • 两个操作数是 undefined, 返回 undefined
  • 同时有 null、NaN 或 undefined,返回第一个对象

  逻辑或操作符是短路操作,即如果第一个操作数的求值结果为 true,就不会对第二个操作数求值了。
  使用逻辑或的这一行为来避免为变量赋 null 或 undefined 值。

var obj = preferredObjcet || backupObject

5.4、乘性操作符

  ECMAScript定义了 3 个乘性操作符:乘法、除法、求模。
  在操作数为非数值的情况下会执行自动的类型转换,后台会先使用 Number() 转型函数将其转换为数值,也就是说,空字符串被当作 0,布尔值 true 被当作 1。

5.4.1、乘法

乘法操作符由一个星号(*)表示,由于计算两个数值的乘积。

var reslult = 10 * 10;

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

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

除法操作符由一个斜线符号(/)表示,执行第二个操作数除第一个操作数的计算。

var a, b;
a 除以b ,a 是被除数、b是除数(a / b)
a 除 b,b是被除数、a是除数(b / a)

除法操作符遵循下列特殊的规则:

  • 操作数都是数值,执行常规的除法计算,如果乘积超过ECMAScript数值的表示范围,返回 Infinity 或 -Infinity。
  • 一个操作数是 NaN,结果是 NaN。
  • Infinity / Infinity, 结果是 NaN。
  • 0 / 0 , 结果是 NaN。
  • 非 0 有限数被 0 除(非零有限数 / 0),结果是 Infinity 或 -Infinity,取决于有符号操作数的符号。
  • Infinity 被任何非 0 数值除( Infinity / 任何非 0 数值),结果是 Infinity 或 -Infinity,取决于有符号操作数的符号。
  • 一个操作数不是数值,在后台调用 Number() 将其转换为数值,再应用上面的规则。
5.4.3、求模

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

var result = 26 % 5;   // 等于 1

求模操作符遵循下列特殊的规则:

  • 操作数都是数值,执行常规的除法计算,返回除得的余数。
  • 无穷大值 % 有限大数值,结果是 NaN。
  • 有限大的数值 % 0, 结果是 NaN 。
  • Infinity % Infinity,结果是 NaN。
  • 有限大的数值 % 无穷大的数值, 结果是被除数(有限大的数值)。
  • 被除数是 0, 结果是 0。
  • 一个操作数不是数值,在后台调用 Number() 将其转换为数值,再应用上面的规则。

5.5、加性操作符

5.5.1、加法
var result = 1 + 2;

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

  • 一个操作数是 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"。

5.5.2、减法

减法遵循规则:

  • 两个操作数都是数值,执行常规的算数减法操作并返回结果
  • 一个操作数是 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() 方法,用得到的结果按前面的规则执行比较。如果没有 valueOf() 方法,调用 toString() 方法,按前面的规则进行比较。
  • 一个操作数是布尔值,先转为数值,再执行比较。
  • 任何操作数与 NaN 进行比较,结果都是 false。

5.7、相等操作符

相等和不相等 —— 先转换再比较
全等和不全等 —— 仅比较而不转换

5.7.1、相等和不相等

  相等操作符由像个等于号(==)表示,如果两个操作数相等,返回 true
不相等操作符由叹号后等等于号(!=)表示,如果两个操作数不相等,返回 true。
这两个操作符都会先转换操作数(通常称为强制转型),然后再比较它们的相等性。

转换不同的数据类型是,遵循规则:

  • 一个操作数是布尔值,转换为数值,false :0, true:1
  • 一个操作数是字符串,另一个是数值,将字符串转为数值
  • 一个操作数是对象,另一个不是,调用对象的 valueOf() 方法

相等和不相等操作符在进行比较时遵循规则:

  • null 和 undefined 是相等的。
  • 比较相等性之前,不能将 null 和 undefined 转换为其他任何值
  • 有一个操作数是 NaN,相等操作返回 false(提示:NaN == NaN ,返回 false)。
  • 两个操作数都是对象,比较是不是同一个对象。如果两个操作数指向同一个对象,相等操作符返回 true。

特殊情况:

表达式
null == undefined true
"NaN" == NaN false
5 == NaN false
NaN == NaN false
NaN != NaN true
false == 0 true
true == 1 true
true == 2 false
undefined == 0 false
null == 0 false
"5" == 5 true
5.7.2、全等和不全等

  全等操作符由 3 个等于号(===)表示,只在两个操作数未经转换就相等的情况下返回 true。

var result1 = ("55" == 55);   // true, 因为转换后相等
var result2 = ("55" === 55);  // false, 因为不同的数据类型不相等

不全等操作符由一个叹号后跟两个等于号(!==)表示。

提示: null == undefined;     // true
      null === unefined;     // false, 类型不同

由于相等和不相等操作符存在类型转换问题,而为了保持代码中数据类型的完整性,推荐使用全等和不全等操作。

1.5.8、条件操作符
variable = boolean_expression ? true_value : false_value;

5.9、赋值操作符

  简单的赋值操作符由等于号(=)表示,其作用就是把右侧的值赋给左侧的变量。
  在等于号(=)前面添加乘性操作符、加性操作符或位操作符,就可以完成复合赋值操作。复合赋值操作相当于常规表达式的简写形式。

var num = 10;
num = num + 10;   =>   num += 10;

复合赋值操作符:

  • 乘/赋值 (*=)
  • 除/赋值 (/=)
  • 模/赋值 (%=)
  • 加/赋值 (+=)
  • 减/赋值 (-=)
  • 左移/赋值 (<<=)
  • 有符号右移/赋值(>>=)
  • 无符号右移/赋值 (>>>=)

复合赋值操作符的主要目的是简化赋值操作,使用它们不会带来任何性能的提升。

5.10、逗号操作符

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

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

  逗号操作符多用于声明多个变量。也可以用于赋值,用于赋值时,逗号操作符总会返回表达式中的最后一项。

var num = (1, 2, 3, 4, 5);    // num 值为 5

6、语句

6.1、if 语句

if (condition) {
    statement1 
} else {
    statement2
}

6.2、do-while 语句

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

do {
    statement
} while (expression);

expression 为 true时,继续循环,为 false时,跳出循环。

6.3、 while 语句

  while 语句属于前测试循环语句,也就是说,在循环体内的代码被执行之前,就会对出口条件求值,因此,循环体内的代码有可能永远不会被执行。
语法:

while (expression) {
    statement
}

6.4、for 语句

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

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

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

6.5、for-in 语句

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

for (property in expression) {
    statement
}

6.6、 label 语句

使用 label 语句可以在代码中添加标签。
语法:

label: statement

示例:

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

  定义的 start 标签可以在将来由 break 或 continue 语句引用。加标签的语句一般都要与 for 语句等循环语句配合使用。

6.7、break 和 continue 语句

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

// break 语句
var num = 0;
for (var i = 1; i < 10; i++) {
    if (i % 5 == 0) {
        break;
    }
    num++;
}
console.log(num);   // 4

// continue 语句
var num = 0;
for (var i = 1; i < 10; i++) {
    if (i % 5 == 0) {
        continue ;
    }
    num++;
}
console.log(num);   // 8

不论是 break 语句还是 continue 语句,都会立即退出当前循环,所以 i = 5 后的 num++ 都不再执行。

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

var num = 0;
outermost: 
for (var i = 0; i < 10; i++) {
    for (lei j = 0; j < 10; j++) {
        if (i == 5 && j == 5) {
            break outermost;    // num 55
            // continue outermost;    // num 95
        }
        num++;
    }
}
console.log(num);   

建议:使用 label 语句,一定要使用描述性的标签,同时不要嵌套过多的循环。

6.8、with 语句

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

with (expression) {
    statement
}

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

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

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

  严格模式下不允许使用 with 语句,否则将视为语法错误。
  由于大量使用 with 语句会导致性能下降,同时也会给调试代码造成困难,因此在开发大型应用程序是,不建议使用 with 语句。

6.9、switch 语句

switch 语句与 if 语句的关系最为密切,是一种流控制语句。

switch (expression) {
    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 语句)。

合并多种情形:

switch (i) {
    case 25:  
    case 35:  
        console.log("25 or 35");
        break;
    case 45:  
        console.log("45");
        break;
    default: 
        console.log("other");
}

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

7、函数

  通过函数可以封装任意多条语句,并可以在任何地方、任何时候调用执行。ECMAScript 中的函数使用 function 关键字来声明,后跟一组参数以及函数体。
语法:

// 声明函数
function functionName (arg0, arg1, ..., argN) {
    statements
}
functionName (); // 调用函数
function sum (num1, num2) {
    return num1 + num2;  // 通过 return 后跟要返回的值来实现返回值
}

  这个函数会在执行完 return 语句后立即停止并退出。因此,位于 return 语句之后的任何代码都永远不会执行。
  return 语句也可以不带任何返回值。这种情况下,函数在停止执行后将返回 undefined 值。这种用法一般在需要提前停止函数执行而又不需要返回值的情况下。

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

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

如果发生以上情况,就会导致语法错误,代码无法执行。

7.1、理解参数

  ECMAScript 函数不介意传递进来多少个参数,也不在乎传进来的参数是什么数据类型。也就是说,即使你定义的函数只接受两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传参数。

  原因:ECMAScript 中的参数在内部是用一个数组来表示的,函数接收到的始终都是这个数组,而不关心数组中包含哪些参数。

  在函数体内部可以通过 arguments 对象来访问这个参数数组,从而获取传递给函数的每一个参数。

  其实,arguments 对象只是与数组类似(并不是 Array 的实例),因为可以使用方括号语法访问它的每一个元素(第一个元素是 arguments[0]),使用 length 属性来确定传递进来多少个参数。

function sayHi (name, message) {
    console.log("hello " + name + "," + message);
}

function sayHi () {
    console.log("hello " + arguments[0] + "," + arguments[1]);
}
// ECMAScript 函数中命名的参数只是提供便利,不是必需的

  通过访问 arguments 对象的 length 属性可以获知有多少个参数传递给了函数。可以利用这个特点来实现不同的功能。

function doAdd () {
    if (arguments.length === 1) {
        console.log(arguments[0] + 10); 
    } else if (arguments.length === 2) {
        console.log(arguments[0] + arguments[1]); 
    }
}

arguments 对象可以与命名参数一起使用。

function doAdd (num1, num2) {
    if (arguments.length === 1) {
        console.log(num1 + 10); 
    } else if (arguments.length === 2) {
        console.log(arguments[0] + num2); 
    }
}

在非严格模式下:
arguments 的值永远与对应命名参数的值保持同步。

function doAdd (num1, num2) {
    arguments[1] = 10; 
    console.log(num2);
}

doAdd(1);     // undefined
doAdd(1, 2);  // 10

  这并不是说读取这两个值回访问相同的内存空间,num2 和 arguments[1] 的内存空间是独立的,但它们的值会同步。

  但如果只传入一个参数,那么为了 arguments[1] 设置的不会反应到命名参数中。这是因为 arguments 对象的长度是由传入的参数个数决定的,不是由定义函数时命名参数的个数决定的。

  没有传递值的命名参数自动被赋予 undefined 值,就像定义变量没有初始化一样。

  严格模式上述赋值无效, 修改 arguments[1] 的值不会影响 num2 的值。

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

7.2、没有重载

  ECMAScript 中定义同名函数,后定义的覆盖先定义的函数,调用函数时仅执行后面的方法。

重载函数:在相同的声明域中的函数名相同的,而参数表不同的,即通过函数的参数表而唯一标识并且来区分函数的一种特殊的函数。

小结

  JavaScript 的核心语言特性在 ECMA-262 中是以名为 ECMAscript 的伪语言的形式定义的。
  ECMAscript 中包含了所有基本的语法、操作符、数据类型以及完成基本的计算任务所必须的对象,但没有对取得输入和产生输出的机制作出规定。

ECMAscript 中的基本要素:

  • ECMAscript 中的基本数据类型包括 Undefined、Null、Boolean、Number 和 String。
  • ECMAscript 没有为整数和浮点数值分别定义不同的数据类型,Number 类型可用于表示所有数值。
  • ECMAscript 中也有一种复杂的数据类型,即 Object 类型,该类型是这门语言中所有对象的基础类型。
  • 严格模式为这门语言中容易出错的地方施加了限制。
  • ECMAscript 中的基本操作符:算数操作符、布尔操作符、关系操作符、相等操作符、赋值操作符。
  • ECMAscript 中的流控制语句: if 语句、for 语句、switch 语句等。
  • 无需指定函数的返回值,因为任何 ECMAscript 函数都可以在任何时候返回任何值。
  • 未指定返回值的函数返回的是一个特殊的 undefined 值。
  • ECMAscript 中没有函数签名的概念,其函数参数是以一个包含零或多个值的数组的形式传递的。
  • 可以向 ECMAScript 函数传递任意数量的参数,并且可以通过 arguments 对象访问这些参数。
  • 由于不存在函数签名的特性,ECMAScript 函数不能重载。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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

推荐阅读更多精彩内容