第 2 章 基本概念

         任何语言的核心都必会然会描述这门语言最基本的工作原理。而描述的内容通常都要涉及这门语言的语法、操作符、数据类型、内置功能等用于构建复杂解决方案的基本概念。

2.1 语法

         ECMAScript语法大量借鉴了C及其他类C语言(如Java和Perl)的语法。

2.1.1 区分大小写

         ECMAScript中的一切(变量、函数名和操作符)都区分大小写。这也就意味着,变量名test和变量名Test分别表示两个不同的变量,而函数名不能使用typeof,因为它是一个关键字,但typeof则完全可以是一个有效的函数名。

2.1.2 标识符

所谓标识符,就是指变量、函数、属性的名字,或者函数的参数。标识符可以是按照下列规则组合起来的一个或多个字符:

Ø  第一个字符必须是一个字母、下划线(_)或一个美元符号($);

Ø  其他字符可以是字母、下划线、美元符号或数字。

标识符中的字母也可以包含扩展的ASCII或Unicode字母字符,但不推荐这样做。按照惯例,ECMAScript标识符采用驼峰大小写格式,也就是第一个字母小写,剩下的每个单词的首字母大写。但是,不能把关键字、保留字、true、false和null用作标识符。

2.1.3 注释

 ECMAScript使用C风格的注释,包括单行注释和块级注释。单行注释以两个斜杠开头,如下所示:

         // 单行注释

 块级注释以一个斜杠和一个星号(/*)开头,一个星号和一个斜杠(*/)结尾,如下所示:

         /*

          *这是一个多行

          *(块级)注释

      */

注释中的第二行和第三行都是以一个星号开头,但不是必需的。之所以添加那两个星号,纯粹是为了提高注释的可读性。

2.1.4 严格模式

         ECMAScript5引入了严格模式(strict mode)的模式。严格模式是为JavaScript定义一种不同的解析和执行模型。在严格模式下,ECMAScript 3中的一些不确定的行为将得到处理,而且对某些不安全的操作也会抛出错误。要在整个脚本中启用严格模式,可以在顶部添加如下代码:"use strict";这行代码看起来像是字符串,而且也没有赋值给任何变量,但其实它是一个编译指示(pragma),用于告诉支持的JavaScript引擎切换到严格模式。这是为不破坏ECMAScript 3语法而特意选定的语法。在函数内部的上方包含这条编译指示,也可以指定函数在严格模式下执行:

         functiondoSomething(){

         "usestrict";

 //函数体

}

2.1.5 语句

         ECMAScript中的语句以一个分号结尾;如果省略分号,则由解析器确定语句的结尾,如下例子所示:var sum=a+b; var diff=a-b;虽然语句结尾的分号不是必需的,但建议任何时候都不要省略它。加入分号可以避免很多错误,开发人员可以放心地通过删除多余的空格来压缩ECMAScript代码(代码行结尾处没有分号会导致压缩错误)。另外,加上分号也会在某些情况下增进代码的性能,这样解析器不必花时间推测应该在哪里插入分号。

         可以使用C风格的语法把多条语句组合到一个代码块中,即代码块以左花括号({)开头,以右花括号(})结尾。

2.2 关键字和保留字

         ECMA-262描述了一组具有特定用途的关键字,这些关键字可用于表示控制语句的开始获结束,或者用于执行特定操作等。按照规则,关键字也是语言保留的,不能用作标识符。一下就是ECMAScript的全部关键字(带*号上标的是第5版新增的关键字):

        第 2 章 基本概念------------(1)_操作符

         ECMA-262还描述了另外一组不能用作标识符的保留字。尽管保留字在这门语言中还没有任何特定的用途,但它们有可能在将来被用作关键字。一下是ECMA-262第3版定义的全部保留字:

        第 2 章 基本概念------------(1)_JavaScript语法_02

         第5版把在非严格模式下运行时的保留字缩减为下列这些:

        第 2 章 基本概念------------(1)_操作符_03

         在严格模式下,第5版还对以下保留字施加了限制:

        第 2 章 基本概念------------(1)_JavaScript数据类型_04

         注意,let和yield是第5版新增的保留字;其他保留字都是第3版定义的。在实现ECMAScript 3的JavaScript引擎中使用关键字作标识符,会导致"Identifier Expected"错误。而使用保留字作标识符可能会也可能不会导致相同的错误,具体取决于特定的引擎。关键字和保留字虽然仍然不能作为标识符使用,但现在可以用作对象的属性名。一般来说,最好都不要使用关键字和保留字作为标识符和属性名,以便与将来的ECMAScript版本兼容。

2.3 变量

         ECMAScript的变量是松散类型的,所谓松散类型就是可以用来保存任何类型的数据。换句话说,每个变量仅仅是一个用于保存值得占位符而已。定义变量时要使用var操作符,后跟变量名,如下所示:“varmessage;”这行代码定义了一个名为message的变量,该变量可以用来保存任何值(像这样未经过初始化的变量,会保存一个特殊的-----undefinded)。ECMAScript也支持直接初始化变量,因此在定义变量的同时就可以设置变量的值,如下所示:“varmessage="hi";”,在此,变量message中保存了一个字符串值"hi"。像这样初始化变量并不会把它标记为字符串类型;初始化的过程就是给变量赋一个值那么简单。因此,可以修改变量值得同时修改值得类型,如下所示:" var message = "hi"; message = 100;",变量message一开始保存了一个字符串值"hi",然后该值又被一个数字值100取代。

       有一点必须注意,即用var操作符定义的变量将成为定义该变量的作用域中的局部变量。也就是说,如果在函数中使用var定义一个变量,那么这个变量在函数退出后就会被销毁,例如:       

function test(){
var message = "hi"; // 局部变量
}
test();
alert(message); // 错误!

       这里,变量message是在函数中使用var定义的。当函数被调用时,就会创建该变量并为其赋值。在此之后,这个变量又会立即被销毁,因此例子的下一行代码会导致错误。像下面省略var操作符,从而创建一个全局变量:     

function test(){
message = "hi"; // 全局变量
}
test();
alert(message); // "hi"

       省略了var操作符,因而message就成了全局变量。这样,只要调用过一次test()函数,这个变量就有了定义,就可以在函数外部的任何地方被访问到。可以使用一条语句定义多个变量,只要像下面这样把每个变量(初始化或不初始化均可)用逗号(,)分隔开即可:  


var   message ="hi",
found = false,
age = 29;

       这个例子定义并初始化了3个变量。由于ECMAScript是松散类型的,因而使用不同类型初始化变量的操作可以放在一条语句中可以完成。

2.4 数据类型

         ECMAScript中有5种简单数据类型(也称为基本数据类型):Undefined、Null、Boolean、Number、String。还有1种复杂数据类型----Object,Object本质上是由一组无序的名值对组成的。ECMAScript不支持任何创建自定义类型的机制,而所有值最终都将是上述6中数据类型之一。

2.4.1 typeof操作符

 ECMAScript是松散型的,typeof操作符被用来检查给定变量的数据类型。对一个值使用typeof操作符可能返回下列某个字符串:

n  "undefined"---------如果这个值未定义;

n  "boolean"------------如果这个值是布尔值;

n  "string"---------------如果这个值是字符串;

n  "number"------------如果这个值是数值;

n  "object"--------------如果这个值是对象或null;

n  "function"-----------如果这个值是函数。

下面是几个使用typeof操作符的例子:       

var message = "some string";
alert(typeof message); //"string"
alert(typeof(message)); // "string"
alert(typeof 95); // "number"

typeof操作符的操作数可以是变量,也可以是数值字面量。注意,typeof是一个操作符而不是函数,因此圆括号可以使用,但不是必需的。

从技术角度讲,函数在ECMAScript中是对象,不是一种数据类型。然而,函数也确实有一些特殊属性,因此通过typeof操作符来区分函数和其他对象是有必要的。

2.4.2 Undefined类型

         Undefined类型只有一个值,即特殊的undefined。在使用var声明变量但未对其加以初始化时,这个变量的值就是undefined,例如:"var message;  alter(message==undefined);"

不过,包含undefined值得变量与尚未定义的变量还是不一样。例如:        

var message; // 这个变量声明之后默认取得了undefined 值
// 下面这个变量并没有声明
// var age
alert(message); // "undefined"
alert(age); // 产生错误

         对于尚未声明过的变量,只能执行一项操作,即使用typeof操作符检测其数据类型。     然而,令人困惑的是:对未初始化的变量执行typeof操作符会返回undefined值,而对未声明的变量执行typeof操作符同样也会返回undefined值。       

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

       结果表明,对未初始化和未声明的变量执行typeof操作符都返回了undefined值。即便未初始化的变量会自动被赋予undefined值,但显示地初始化变量依然是明智的选择。如果能够做到这一点,当typeof操作符返回"undefined"值时,就知道检测的变量还没有被声明,而不是尚未初始化。

2.4.3 Null类型

         Null类型是第二个只有一个值得数据类型,这个特殊的值是null。从逻辑角度来看,null值表示一个空对象指针,而这也正是使用typeof操作符检测null值时会返回"object"的原因,例如:"var car=null; alter(typeof car);   //"object"",如果定义的变量准备在将来用于保存对象,那么最好将该变量初始化为null而不是其他值。只要直接检查null值就可以知道相应的变量是否已经保存了一个对象的引用。实际上,undefined值是派生自null值的,因此ECMA-262规定对它们的相等性测试要返回true:alter(null==undefined)。