3.1 JavaScript语法
JavaScript是一门解释型、弱类型的脚本语言,也是Web开发最重要的语言之一。JavaScript由ECMAScript、DOM(文档对象模型)、BOM(浏览器对象模型)三部分组成。ECMAScript规定了JavaScript的语法核心,这也是本节重点介绍的内容。
3.1.1 变量
1.交互式运行环境——REPL
Node.js提供了一个交互式运行环境——REPL。在这个交互式环境中可以运行简单的应用程序。在控制台直接输入node即可进入这个环境,此时控制台会显示一个提示符“>”,表明我们已经进入这个环境,如图3.1中的箭头所示。
图3.1 进入REPL运行环境
提示
如果要退出该运行环境,连续按两次Ctrl+C快捷键,或者输入.exit。Node.js的命令需要在前面加点。例如,可用.help查看所有命令。
本节中的所有代码都会在这个环境中使用和运行。
2.浏览器环境——Firefox
当然,读者也可以在浏览器的控制台运行。以Firefox浏览器为例,通过按F12键或者Ctrl+Shift+I快捷键打开开发者工具,在开发者工具栏中选择Console面板,如图3.2所示。在Console中也是显示提示符“>”,和REPL的使用方法一致。
图3.2 浏览器的Console面板
3.关键字var
JavaScript的变量通过关键字var来声明。前面说过JavaScript是一门弱类型的编程语言,JavaScript的所有数据类型都可以用var关键字来声明,通过var变量名=值的形式就可以对变量同时进行声明和赋值。和许多语言一样,JavaScript通过分号“;”来分隔不同的语句,以下这段代码就声明了两个变量:
var a = "node.js"; var b = 10;
4.变量的命名
JavaScript规定变量名必须以字母、美元符($)、下划线(_)三者之一开头,同时JavaScript区分字母大小写,字母大小写不同也就意味着是不同的两个变量。同时,JavaScript不区分单引号与双引号,因此上一个例子若把双引号换成单引号,程序表示的意思是一样的:
var a = 'node.js'; var b = 10;
5.变量提升机制
JavaScript中存在变量提升机制,也就是所有的变量声明在运行时都会提升到代码的最前方。例如,上个例子在运行时实际上会先声明两个变量再赋值:
var a; var b; a = "node.js"; b = 10;
通过一个更直观的例子或许会让读者更易理解变量提升。在REPL中试图使用一个未声明的变量时会出现is not defined错误,如图3.3所示。
图3.3 变量未声明错误
如果试图使用一个已经声明却未赋值的变量,那么这个变量所代表的是undefined,如图3.4所示。
图3.4 已经声明却未赋值
提示
图3.4中有两行undefined:一个是白色,一个是半透明白色。执行node语句,在没有任何返回值的时候总是会输出一个undefined,读者不必介意,这不是错误。白色语句是正常输出的内容。
使用一个在后来定义赋值的代码时会返回undefined,如图3.5所示。
图3.5 先使用后声明赋值
可以发现这段代码返回undefined正是因为变量提升,实际运行的代码如下:
var a; console.log(a); a = 10;
3.1.2 注释
JavaScript中的注释和很多其他编程语言类似,以双斜杠(//)代表单行注释,以“/*注释内容*/”形式代表多行注释。
// 这是单行注释 /* 这是 多行 注释 */
3.1.3 数据类型
JavaScript中的数据类型可以分为简单数据类型和复杂数据类型。简单数据类型有undefined、boolean、number、string、null,复杂数据类型只有object。object由一组无序的键值对组成。
1.利用typeof区分数据类型
利用操作符typeof可以部分区分以上数据类型。typeof返回的值有undefined、boolean、number、string、object和function。下面举一个例子。
【代码3-1】
【代码说明】
可以看到null和object都返回了object,这是因为null实际上是一个空对象指针,当一个变量只声明但未赋值时就会返回undefined。
number和string数据类型分别指数字类型和字符串类型;boolean类型和其他语言一样,仅有true和false两个值;null仅有一个值null。
2.利用Boolean()转化数据类型
JavaScript中可以利用Boolean()函数将其他数据类型转化为布尔值。需要注意的是,空字符串、0、null、undefined、NaN都将转化为false,其他值则会转化为true。下面举一个例子。
【代码3-2】
3.1.4 函数
在JavaScript中,声明一个函数只需要使用function关键字即可,如声明一个求和的函数,代码如下:
function add(num1, num2) { return num1 + num2; }
当然,函数同样可以作为一个值传递给一个变量,例如:
var add = function(num1, num2) { return num1 + num2; }
调用一个函数同样很简单,只需要在函数声明之后使用“函数名(参数)”的形式调用即可,如调用上面的函数:
function add(num1, num2) { return num1 + num2; } add(1, 2); // 3 add(3,5); //8
函数中默认带有一个arguments对象,这是一个类数组对象。arguments记录了传递给函数的参数信息,因为JavaScript中的函数调用时,参数个数并不需要和定义函数时的个数一致。在上面的add()函数中多添加几个参数,函数仍然会正常执行,例如:
function add(num1, num2) { return num1 + num2; } add(1,2,4,5,5); // 3 add(3,5,2,3); //8
利用好这一点和arguments类数组特性可以对上述的add函数拓展一下,让这个函数无论接收多少个参数,总能返回这些数值的和:
function add() { var sum = 0; for(var i = 0, max = arguments.length; i < max; i++) { sum += arguments[i]; } return sum; } add(2,3,4); // 9 add(2,4,5); // 11
还可以利用JavaScript中的arguments类数组对象模拟函数重载。当然,实际上JavaScript并不支持函数重载,比如通过检测arguments对象的length属性做出不同的反应来模拟重载。下面给出一个完整的例子。
【代码3-3】
以上代码的运行效果如图3.6所示。
图3.6 运行效果
【代码说明】
arguments对象是一个类数组对象。通过数组的slice()函数可以把arguments对象转化为一个真正的数组,这样就可以使用数组的所有函数,而不用担心出现其他问题了。
function funName() { var arguments = [].slice.call(arguments); // the code of function }
3.1.5 闭包
JavaScript中的变量可以分为全局变量和局部变量。JavaScript中的函数自然可以读取到全局变量,而函数外部并不能读取到函数内部定义的变量,例如:
【代码3-4】
当然,这需要在定义变量的时候使用var关键字定义。不用var关键字定义的话,实际上这个变量会成为全局对象的一个属性。在Node.js中,全局对象是global,如果上面代码中的str2变量不使用var定义,str2就会成为一个全局变量,函数外部也是可以读取到这个变量的,例如:
【代码3-5】
提示
建议所有的变量都使用var关键字进行声明(或定义),以避免不必要的错误出现。
JavaScript中的闭包可以让函数读取到其他函数内部的变量,如下代码就可以让函数之外读取到函数内部定义的变量,这就是最简单的闭包。
【代码3-6】
以上就是JavaScript的简要介绍。更多关于JavaScript的知识,读者可以阅读相关的书籍进行学习和掌握。进行Node.js的学习之前,读者应该对JavaScript有一定的了解。