代码改变世界

javascript中的函数

2006-10-15 20:00  Anders Cui  阅读(1471)  评论(0编辑  收藏  举报
问题:
    在JavaScript中创建和使用函数。包括常规函数、嵌套函数、匿名函数。

解决方案:
    一、常规具名函数:
    如果函数不接受参数,使用下面形式定义:
    function myFunctionName()
    {
        
// 函数中的语句
    }
    如果函数接受参数,使用下面形式定义:
    function myFunctionName(paramVar1, paramVar2[, , paramVarN])
    {
        
// 函数中的语句
    }

    可以根据需要定义相应数量的参数变量,这些变量在函数内部成为局部变量。根据JavaScript的自由类型约定,参数变量可以持有任意合法类型的数据。函数定义中的花括号仅当函数体包含两条及两条以上语句时才是必要的,但作为一个好的编码习惯,建议即使函数仅包含一条语句,也要使用花括号,以增强代码的可读性。

讨论:
    函数在JavaScript中是一个对象类型,函数的名称是该类型的大小写敏感的标识符。函数名不能是JavaScript为保留字,也不能与全局变量名或页面元素的ID相同。如果同一页面上存在几个具有相同名称的函数,那么只有最后一个有效。也就是说,JavaScript不支持重载。

    调用函数时,要加上圆括号:
    myFunc();
    myFunc2(
"hello"20);
    有时需要将函数引用赋值给对象的属性。比如,将事件处理函数赋给对象属性,此时只要写函数的名称:
    document.onclick = myFunc;
    像这样的赋值语句并非调用函数,而是为将来的调用作好准备。

    调用函数时,JavaScript不要求传入与函数定义中相同数量的参数,如果需要,可以在不同的地方传入不同数量的参数。此时,再使用参数变量就不太合适了,可以使用该函数对象的arguments属性:
    function argumentFunc(para1, para2)
    {
        
for(var i = 0; i < argumentFunc.arguments.length; i++)
        {
            window.alert(
"parameter " + i.toString() + "" + argumentFunc.arguments[i]);
        }
    }

    通常情况下(嵌套函数除外),函数的作用域是全局的。与全局变量一样,全局函数可以在其它window/frame中引用。

    一个函数的代码长度是一个风格问题。为便于调试和维护,应将一个较大的函数分解为几个较小的子函数。如果看到一个函数内,有些语句多次出现,这些语句最好拿出来写在一个函数内。
    另一个风格方面的问题是花括号的位置。一种常见的风格(也是本人的习惯)是如下:
    function myFunc()
    {
        
// 函数中的语句;
    }    
    这样的结构感觉最清晰,有条理。
    另一种常见的风格是:
    function myFunc( ) {
        
// 函数中的语句;
    }
    对那些只有一行的函数还可以这样写:function myFunc() { // 函数中的语句; }
    可以根据自己的代码阅读习惯选择合适的风格。

    二、匿名函数

    有时需要以表达式的形式创建函数,比如,作为参数传递给对象的构造函数或赋值为一个对象的方法。这时可以使用另一种语法来定义一个函数而不用显示命名,这就是匿名函数(anonymous function)。除了没有标识符(函数名),匿名函数具备常规函数具备的一切要素。语法如下:
    var someReference = function()
                        {
                            
// statements go here;
                        };    
    花括号中的语句是以分号隔开的JavaScript语句。如有必要,也可以为其定义参数变量。按如下语法来调用匿名函数:
    someReference();                        
    看起来,someReference有点像C#中的委托:)

    创建匿名函数的语句返回一个function类型的对象。因此,将匿名函数赋值给需要函数引用的地方。比如创建自定义对象Employee,为其添加方法show时,可以像下面这样使用已经定义的常规函数:
    function Employee(name, age)
    {
        
this.name = name;
        
this.age = age;
        
this.show = show;
    }
    
function show()
    {
        alert(
"Employee " + this.name + " is " + this.age + " years old.");
    }
    也可以使用匿名方法:
    function Employee(name, age)
    {
        
this.name = name;
        
this.age = age;
        
this.show = function() { alert("Employee " + this.name + " is " + this.age + " years old."); }
    }

    三、嵌套函数
   
    有时需要创建仅对某一特定函数可见的函数(有点类似与类型的成员方法)。在IE4和NN4之后的版本中,可以使用如下的语法来创建嵌套函数:
    function myFuncA()
    {
        
// 函数myFuncA的语句;
        function myFuncB()
        {
            
// 函数myFuncB的语句;
        }
    }

    在这种结构中,内层函数myFuncB只能被外层函数myFuncA中的语句访问。myFuncB中的语句可以访问myFuncA中的变量,也可以访问全局变量。但myFuncA中的语句不能访问myFuncB中的变量。
    嵌套函数的基本原理是:使内层函数仅对外层函数可见来封装外层函数相关的所有行为。因为嵌套函数不是直接向全局作用域公开,所以可以对全局函数或其它函数的子函数使用相同的函数名。
    Netscape6及其后续版本以一种方便同时也是合理的方式扩展了嵌套函数:将嵌套函数视为其外层函数对象的一个成员方法。这一特性实现的方式有很多有趣的衍生物。考虑如下的测试函数:
    function myFuncA()
    {
        
var valueA = "A";
        myFuncB();
        
function myFuncB()
        {
            
var valueB = "B";
            alert(valueB);
            alert(valueA);
        }
    }
    在全局作用域内调用myFuncA()的时候,它会调用嵌套函数myFuncB(),myFuncB()会分别呈现valueB和valueA的值。IE也如所期望的有着相同的行为。但在Netscape6及后续版本中,你可以以如下方式调用嵌套函数:
    myFuncA.myFuncB();
    此时外层函数myFuncA不会被调用, 变量valueA没有初始化。当myFuncB()执行的时候,它会显示valueB的值, 但valueA则显示为undefined。因此,只有外层函数调用内层函数时,嵌套的内层函数才能访问外层函数的变量的值。

    参考:(Oreilly)Java Script And Dhtml Cookbook