js函数 JavaScript 函数调用

菜鸟课程中有js代码的书写规范

函数的定义

JavaScript 使用关键字 function 定义函数。

函数可以通过声明定义,也可以是一个表达式。

函数表达式

 JavaScript 函数可以通过一个表达式定义。

函数表达式可以存储在变量中:

<p>函数可以存储在变量中:</p>
<p id="demo"></p>
<script>
var x = function (a, b) {return a * b};
document.getElementById("demo").innerHTML = x;
</script>
//上述函数以分号结尾,因为它是一个执行语句。

函数声明

1 <p id="demo"></p>
2 <script>
3 function myFunction(a,b){
4     return a*b;
5 }
6 document.getElementById("demo").innerHTML=myFunction(4,3);
7 </script>
//分号是用来分隔可执行JavaScript语句。 

//由于函数声明不是一个可执行语句,所以不以分号结束.

 

Arguments 对象

JavaScript 函数有个内置的对象 arguments 对象。

argument 对象包含了函数调用的参数数组。

通过这种方式你可以很方便的找到最后一个参数的值:

 1 <p>查找最大的数。</p>
 2 <p id="demo"></p>
 3 <script>
 4 function findMax() {
 5     var i, max = 0;
 6     for(i = 0; i < arguments.length; i++) {
 7         if (arguments[i] > max) {
 8             max = arguments[i];
 9         }
10     }
11     return max;
12 } 
13 document.getElementById("demo").innerHTML = findMax(4, 5, 6);
14 </script>

 


JavaScript 函数有 4 种调用方式。

每种方式的不同方式在于 this 的初始化。


this 关键字

一般而言,在Javascript中,this指向函数执行时的当前对象。

注意 this 是保留关键字,你不能修改 this 的值。

全局对象

当函数没有被自身的对象调用时, this 的值就会变成全局对象。

在 web 浏览器中全局对象是浏览器窗口(window 对象)。

该实例返回 this 的值是 window 对象:

 1 <p id="demo"></p>
 2 
 3 <script>
 4 
 5 function myFunction() {
 7     return this;
 9 }
11 document.getElementById("demo").innerHTML = myFunction(); 
12 
13 </script>

注意:函数作为全局对象调用,会使 this 的值成为全局对象。

作为一个函数调用

1 <p>
2 全局函数 (myFunction) 返回参数参数相乘的结果:
3 </p>
4 <p id="demo"></p>
5 <script>
6 function myFunction(a, b) {
7     return a * b;
8 }
9 document.getElementById("demo").innerHTML = myFunction(10, 2); 

函数作为方法调用

在 JavaScript 中你可以将函数定义为对象的方法。

以下实例创建了一个对象 (myObject), 对象有两个属性 (firstNamelastName), 及一个方法 (fullName):

 1 <p>myObject.fullName() 返回 John Doe:</p>
 2 <p id="demo"></p>
 3 <script>
 4 var myObject = {
 5     firstName:"John",
 6     lastName: "Doe",
 7     fullName: function() {
 8         return this.firstName + " " + this.lastName;
 9     }
10 }
11 document.getElementById("demo").innerHTML = myObject.fullName(); 

注意:实例中 this 的值为 myObject 对象。

使用构造函数调用函数

如果函数调用前使用了 new 关键字, 则是调用了构造函数。

这看起来就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象:

 1 <p>该实例中, myFunction 是函数构造函数:</p>
 2 <p id="demo"></p>
 3 <script>
 4 function myFunction(arg1, arg2) {
 5     this.firstName = arg1;
 6     this.lastName  = arg2;
 7 }
 8 var x = new myFunction("John","Doe")
 9 document.getElementById("demo").innerHTML = x.firstName; 
10 </script>

注意:构造函数的调用会创建一个新的对象。新对象会继承构造函数的属性和方法。

注意:构造函数中 this 关键字没有任何的值。this 的值在函数调用时实例化对象(new object)时创建。

作为函数方法调用函数

在 JavaScript 中, 函数是对象。JavaScript 函数有它的属性和方法。

call()apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身。

 1  function myFunction(a, b) {
 2     return a * b;
 3 }
 4 myFunction.call(myObject, 10, 2);      // 返回 20
 5 
 6 function myFunction(a, b) {
 7     return a * b;
 8 }
 9 myArray = [10,2];
10 myFunction.apply(myObject, myArray);   // 返回 20 

两个方法都使用了对象本身作为第一个参数。 两者的区别在于第二个参数: apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。

注意:通过 call() 或 apply() 方法你可以设置 this 的值, 且作为已存在对象的新方法调用。

--------------------------------------------------------------------------------------------------------

三、闭包的概念

上一节代码中的f2函数,就是闭包。

各种专业文献上的“闭包”(closure)定义非常抽象,很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

--------------------------------------------------------------------------------------------------------b

四、闭包的用途

闭包可以用在许多地方。它的最大用处有两个,个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中

怎么来理解这句话呢?请看下面的代码。


Js代码

  function f1(){

    var n=999;

    nAdd=function(){n+=1}

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999

  nAdd();

  result(); // 1000

在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个

匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

-------------------------------------------------------------------------------------------------------- 

五、使用闭包的注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便

改变父函数内部变量的值。

--------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------
JavaScript闭包例子

function outerFun()
 {
  var a=0;
  function innerFun()
  {
   a++;
   alert(a);
  }    
 }
innerFun()

上面的代码是错误的.innerFun()的作用域在outerFun()内部,所在outerFun()外部调用它是错误的.

改成如下,也就是闭包:

Js代码

function outerFun()
{
 var a=0;
 function innerFun()
 {
  a++;
  alert(a);
 }
 return innerFun;  //注意这里
}
var obj=outerFun();
obj();  //结果为1
obj();  //结果为2
var obj2=outerFun();
obj2();  //结果为1
obj2();  //结果为2

什么是闭包:

当内部函数 在定义它的作用域 的外部 被引用时,就创建了该内部函数的闭包 ,如果内部函数引用了位于外部函数的变量,当外部函数调用完毕后,这些变量在内存不会被 释放,因为闭包需要它们.

可查看网址:http://www.jb51.net/article/24101.htm来获取闭包是深入理解

作为一个函数调用