一、ECMAScript 函数概述
1、什么是函数?
函数是一组可以随时随地运行的语句。
函数是 ECMAScript 的核心。
函数是由这样的方式进行声明的:关键字 function、函数名、一组参数,以及置于括号中的待执行代码。
函数的基本语法是这样的:
function functionName(arg0, arg1, ... argN) {
statements
}
例如:
function sayHi(sName, sMessage) {
alert("Hello " + sName + sMessage);
}
2、如何调用函数?
函数可以通过其名字加上括号中的参数进行调用,如果有多个参数。
如果您想调用上例中的那个函数,可以使用如下的代码:
sayHi("David", " Nice to meet you!")
调用上面的函数 sayHi() 会生成一个警告窗口。
3、函数如何返回值?
函数只需要使用return
运算符后跟要返回的值即可。
函数在执行过 return 语句后立即停止代码。因此,return 语句后的代码都不会被执行。
注释:如果函数无明确的返回值,或调用了没有参数的 return 语句,那么它真正返回的值是 undefined。
二、ECMAScript arguments 对象
1、arguments 对象
在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。
例如,在函数 sayHi() 中,第一个参数是 message。用 arguments[0] 也可以访问这个值,即第一个参数的值(第一个参数位于位置 0,第二个参数位于位置 1,依此类推)。
因此,无需明确命名参数,就可以重写函数:
function sayHi() {
if (arguments[0] == "bye") {
return;
}
alert(arguments[0]);
}
2、检测参数个数
还可以用 arguments 对象检测函数的参数个数,引用属性 arguments.length
即可。
function howManyArgs() {
alert(arguments.length);
}
howManyArgs("string", 45);
howManyArgs();
howManyArgs(12);
上面这段代码将依次显示 "2"、"0" 和 "1"。
注释:
- ECMAScript 不会验证传递给函数的参数个数是否等于函数定义的参数个数。
- 开发者定义的函数都可以接受任意个数的参数(根据 Netscape 的文档,最多可接受 255 个),而不会引发任何错误。
- 任何遗漏的参数都会以 undefined 传递给函数,多余的函数将忽略。
3、模拟函数重载
用 arguments 对象判断传递给函数的参数个数,即可模拟函数重载:
function doAdd() {
if(arguments.length == 1) { //arguments.length用于判断参数的个数
alert(arguments[0] + 5);
} else if(arguments.length == 2) {
alert(arguments[0] + arguments[1]);
}
}
doAdd(10); //输出 "15"
doAdd(40, 20); //输出 "60"
三、ECMAScript Function 对象(类)
ECMAScript 的函数实际上是功能完整的对象。
1、Function 对象(类)
ECMAScript 最令人感兴趣的可能莫过于函数实际上是功能完整的对象。
Function 类可以表示开发者定义的任何函数。
用 Function 类直接创建函数的语法如下:
var function_name = new function(arg1, arg2, ..., argN, function_body)
在上面的形式中,每个 arg 都是一个参数,最后一个参数是函数主体(要执行的代码)。这些参数必须是字符串。
实例:
var sayHi =
new Function("sName", "sMessage", "alert(\"Hello \" + sName + sMessage);");
2、Function 对象的 length 属性
如前所述,函数属于引用类型,所以它们也有属性和方法。
ECMAScript 定义的属性 length 声明了函数期望的参数个数
ECMAScript 可以接受任意多个参数(最多 25 个)
3、Function 对象的方法
Function 对象也有与所有对象共享的 valueOf() 方法和 toString() 方法。这两个方法返回的都是函数的源代码,在调试时尤其有用。例如:
function doAdd(iNum) {
alert(iNum + 10);
}
document.write(doAdd.toString());
返回结果:
function doAdd(iNum) { alert(iNum + 10); }
四、ECMAScript 闭包(closure)
ECMAScript 最易让人误解的一点是,它支持闭包(closure)。
闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。
1、简单的闭包实例
在 ECMAScript 中使用全局变量是一个简单的闭包实例。请思考下面这段代码:
var sMessage = "hello world";
function sayHelloWorld() {
alert(sMessage);
}
sayHelloWorld();
2、复杂的闭包实例
在一个函数中定义另一个会使闭包变得更加复杂。例如:
var iBaseNum = 10;
function addNum(iNum1, iNum2) {
function doAdd() {
return iNum1 + iNum2 + iBaseNum;
}
return doAdd();
}
这里要掌握的重要概念是,doAdd() 函数根本不接受参数,它使用的值是从执行环境中获取的。
补充
五、变量对象(Variable Object)
1、介绍
大多数ECMAScript程序员应该都知道变量与执行上下文有密切关系:
var a = 10; // 全局上下文中的变量
(function () {
var b = 20; // function上下文中的局部变量
})();
alert(a); // 10
alert(b); // 全局变量 "b" 没有声明
并且,很多程序员也都知道,当前ECMAScript规范指出独立作用域只能通过“函数(function)”代码类型的执行上下文创建。也就是说,相对于C/C++来说,ECMAScript里的for循环并不能创建一个局部的上下文。
for (var k in {a: 1, b: 2}) {
alert(k);
}
alert(k); // 尽管循环已经结束但变量k依然在当前作用域
2、数据声明
如果变量与执行上下文相关,那变量自己应该知道它的数据存储在哪里,并且知道如何访问。这种机制称为变量对象(variable object)。
变量对象(缩写为VO)是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的以下内容:
- 变量 (var, 变量声明);
- 函数声明 (FunctionDeclaration, 缩写为FD);
- 函数的形参
参考资料
【1.ECMAScript 函数概述】http://www.w3school.com.cn/js/pro_js_functions.asp
【2.深入理解JavaScript系列(12):变量对象(Variable Object)】http://www.cnblogs.com/TomXu/archive/2012/01/16/2309728.html