原文地址:http://sheneyan.com/g.php/tech/article/js/jsfunc.html
javascript的函数
作者:F. Permadi
译者:Sheneyan(子乌)
时间:2006.01.03
英文原文: INTRODUCTION TO JavaScript Functions
子乌注:一篇相当不错的function入门文章,个人感觉相当经典。
词语翻译列表 function:函数(Function未翻译) declare:定义 assign:指派,分配 functionbody:函数体(就是函数的内容) object:对象 property:属性 unnamed:匿名(在这里没翻译成未命名) object oriented programming:面相对相编程 class:类(比如后面的class data type我翻译成类数据类型) pointer:指针 reassign:重新分配 nest:嵌套 feature:功能,特性 local/global:局部/全局 blueprint:蓝图(?) user defined:用户自定义 instance:实例 prototype:原型(除了标题都不翻译) internal:内部 constructor:构造器 duplication:复制 函数:定义有以下这些方法可以定义一个函数。所有这些都是有效的,但是它们在后台如何实现的则有一些差别。
常用的写法一般大家都用这个写法来定义一个函数:
functionName([parameters]){functionBody};
Example D1:
Language:javascript, parsed in: 0.005 seconds, using GeSHi 1.0.7.12function add(a, b) 
{                     
  return a+b;
}                     
alert(add(1,2));        // 结果 3运行示例
当我们这么定义函数的时候,函数内容会被编译(但不会立即执行,除非我们去调用它)。而且,也许你不知道,当这个函数创建的时候有一个同名的对象也被创建。就我们的例子来说,我们现在有一个对象叫做“add”(要更深入了解,看底下函数:对象节。)
匿名函数我们也可以通过指派一个变量名给匿名函数的方式来定义它。
Example D2 
Language:javascript, parsed in: 0.006 seconds, using GeSHi 1.0.7.12var add=function(a, b) 
{                     
  return a+b;
}                     
alert(add(1,2));        // 结果 3运行示例
这个代码和前一个例子做了同样的事情。也许语法看起来比较奇怪,但它应该更能让你感觉到函数是一个对象,而且我们只是为这个对指派了一个名称。可以把它看做和var myVar=[1,2,3]一样的语句。以这种方式声明的函数内容也一样会被编译。
当我们指派一个这样的函数的时候,我们并不一定要求必须是匿名函数。在这里,我作了和ExampleD2一样的事情,但我加了函数名“theAdd”,而且我可以通过调用函数名或者是那个变量来引用函数。
Example D2A
Language:javascript, parsed in: 0.008 seconds, using GeSHi 1.0.7.12var add=function theAdd(a, b) 
{                     
  return a+b;
}                     
alert(add(1,2));           // 结果 3
alert(theAdd(1,2));        // 结果也是 3运行示例
使用这种方式来定义函数在面向对象编程中是很有用的,因为我们能像底下这样使一个函数成为一个对象的属性。
Language:javascript, parsed in: 0.005 seconds, using GeSHi 1.0.7.12var myObject=new Object();
myObject.add=function(a,b){return a+b};  
// myObject 现在有一个叫做“add”的属性(或方法)
// 而且我能够象下面这样使用它
myObject.add(1, 2);new我们也能够通过使用运算符new来定义一个函数。
这是一个最少见的定义函数的方式并且并不推荐使用这种方式除非有特殊的理由(可能的理由见下)。语法如下:
varName=new Function([param1Name, param2Name,...paramNName], functionBody);
Example D3: 
Language:javascript, parsed in: 0.004 seconds, using GeSHi 1.0.7.12var add=new Function("a", "b", "return a+b;");
alert(add(3,4));        // 结果 7运行示例
我在这里有两个参数叫做a和b,而函数体返回a和b的和。请注意new Function(...)使用了大写F,而不是小写f。 这就告诉javascript,我们将要创建一个类型是Function的对象。 还要注意到,参数名和函数体都是作为字符串而被传递。我们可以随心所欲的增加参数,javascript知道函数体会是右括号前的最后一个字符串(如果没有参数,你能够只写函数体)。你没必要将所有东西都写在一行里(使用\或者使用字符串连接符+来分隔长代码)。\标记告诉JavaScript在下一行查找字符串的其余部分。例子如下:
Example D4 
Language:javascript, parsed in: 0.007 seconds, using GeSHi 1.0.7.12// 注意 "+"
// 和 "\"的不同用法
var add=new Function("a", "b", 
  "alert" +                      
  "('adding '+a+' and ' +b);\
   return a+b;");
alert(add(3,4));        // 结果 7javascript:exampleD4();
采用这种方式定义函数会导致函数并没被编译,而且它有可能会比用其它方式定义的函数要慢。至于为什么,看一下这个代码:
Example D5
Language:javascript, parsed in: 0.022 seconds, using GeSHi 1.0.7.12function createMyFunction(myOperator)
{
  return new Function("a", "b", "return a" + myOperator + "b;");
}var add=createMyFunction("+");                // 创建函数 "add" 
var subtract=createMyFunction("-");           // 创建函数 "subtract" 
var multiply=createMyFunction("*");           // 创建函数 "multiply" 
// test the functions
alert("加的结果="+add(10,2));                  // 结果是 12
alert("减的结果="+subtract(10,2));             // 结果是 8
alert("乘的结果="+multiply(10,2));             // 结果是 20
alert(add);运行示例
这个有趣的例子创建了三个不同的function,通过实时传递不同的参数来创建一个新Function。因为编译器没法知道最终代码会是什么样子的,所以new Function(...)的内容不会被编译。那这有什么好处呢?嗯,举个例子,如果你需要用户能够创建他们自己的函数的时候这个功能也许很有用,比如在游戏里。我们也许需要允许用户添加“行为”给一个“player”。但是,再说一次,一般情况下,我们应该避免使用这种形式,除非有一个特殊的目的。
函数:对象函数是javascript中的一种特殊形式的对象。它是第一个类数据类型。这意味着我们能够给它增加属性。这里有一些需要注意的有趣观点: 
对象的创建就像刚才提及的,当我们定义一个函数时,javascript实际上在后台为你创建了一个对象。这个对象的名称就是函数名本身。这个对象的类型是function。在下面的例子,我们也许不会意识到这一点,但我们实际上已经创建了一个对象:它叫做Ball。
Example 1 
Language:javascript, parsed in: 0.005 seconds, using GeSHi 1.0.7.12function Ball()       // 也许看起来有点奇怪,但是这个声明
{                     // 创建了一个叫做Ball的对象
  i=1;
}                     
alert(typeof Ball);     // 结果 "function"运行示例
我们甚至能将这个对象的内容打印出来而且它会输出这个函数的实际代码,Example 2: 点击 alert(Ball);来看看Ball的内容。
属性的添加我们能够添加给Object添加属性,包括对象function。因为定义一个函数的实质是创建一个对象。我们能够“暗地里”给函数添加属性。比如,我们这里定义了函数Ball,并添加属性callsign。
Language:javascript, parsed in: 0.006 seconds, using GeSHi 1.0.7.12function Ball()       // 也许看起来有点奇怪,但是这个声明
{                     // 创建了一个叫做Ball的对象,而且你能够
}                     // 引用它或者象下面那样给它增加属性
Ball.callsign="The Ball"; // 给Ball增加属性
alert(Ball.callsign); // 输出 "The Ball"运行示例
指针因为function是一个对象,我们能够为一个function分配一个指针。如下例,变量ptr指向了对象myFunction。
Language:javascript, parsed in: 0.005 seconds, using GeSHi 1.0.7.12function myFunction(message) 

  alert(message);
}
var ptr=myFunction;  // ptr指向了myFunction
ptr("hello");        // 这句会执行myFunction:输出"hello"运行示例
我们能够运行这个函数,就好像这个函数名已经被指针名代替了一样。所以在上面,这行ptr("hello"); 和myFunction("hello");的意义是一样的。
指向函数的指针在面向对象编程中相当有用。例如:当我们有多个对象指向同一个函数的时候(如下):
Example 4A 
Language:javascript, parsed in: 0.017 seconds, using GeSHi 1.0.7.12function sayName(name) 

  alert(name);
}
var object1=new Object();      // 创建三个对象
var object2=new Object();
var object3=new Object();
object1.sayMyName=sayName;       // 将这个函数指派给所有对象
object2.sayMyName=sayName;
object3.sayMyName=sayName;
object1.sayMyName("object1");    // 输出 "object1"
object2.sayMyName("object2");    // 输出 "object2"
object3.sayMyName("object3");    // 输出 "object3"运行示例
 
因为只有指针被保存(而不是函数本身),当我们改变函数对象自身的时候,所有指向那个函数的指针都会发生变化。我们能够在底下看到:
Example 5: 
Language:javascript, parsed in: 0.015 seconds, using GeSHi 1.0.7.12function myFunction() 

  alert(myFunction.message);
}
myFunction.message="old";
var ptr1=myFunction;                 // ptr1 指向 myFunction
var ptr2=myFunction;                 // ptr2 也指向 myFunctionptr1();         // 输出 "old"
ptr2();                              // 输出 "old"myFunction.message="new";ptr1();         // 输出 "new"
ptr2();                              // 输出 "new"运行示例
指针的指向我们能够在一个函数创建之后重新分配它,但是我们需要指向函数对象本身,而不是指向它的指针。在下例中,我将改变myfunction()的内容。
Example 6: 
Language:javascript, parsed in: 0.007 seconds, using GeSHi 1.0.7.12function myFunction() 

  alert("Old");
}
myFunction(); // 输出 "Old"
myFunction=function()
{
  alert("New");
};
myFunction(); // 输出 "New"运行示例
旧函数哪里去了??被抛弃了。
 
如果我们需要保留它,我们可以在改变它之前给它分配一个指针。
Example 6A: 
Language:javascript, parsed in: 0.008 seconds, using GeSHi 1.0.7.12function myFunction() 

  alert("Old");
}
var savedFuncion=myFunction;
myFunction=function()
{
  alert("New");
};
myFunction();    // 输出 "New"
savedFuncion();  // 输出 "Old"运行示例
 
不过要小心,象下面这样的例子并不会有作用,因为是创建了另一个叫做myFunctionPtr的函数而不是修改它。
Example 6B: 
Language:javascript, parsed in: 0.009 seconds, using GeSHi 1.0.7.12function myFunction() 

  alert("Old");
}
var savedFunc=myFunction;
savedFunc=function()
{
  alert("New");
};
myFunction();            // 输出 "Old"
savedFunc();             // 输出 "New"