函数

来源:互联网 发布:最新云豹直播系统源码 编辑:程序博客网 时间:2024/06/09 11:43
  1. Function类型,即函数的类型(函数其实也是一种数据类型<function类型>)
  1. 一个典型的js函数定义如下:
function 函数名称(参数表){
    函数执行部分;
}
(1)js中的函数是没有返回值类型的
(2)注意:参数列表直接写形参名即可,不用写var,也不能指定类型(如number什么的)
(3)调用的时候直接写:函数名称(参数)
(4)参数列表相当于函数的入口,return相当于函数的出口
(5)在js中函数是可以嵌套定义的,但是尽量不要这样去定义
  1. return语句:return返回函数的返回值并结束函数的运行(也就是说函数里面return语句后面的语句就不会再执行了)
  2. 函数也可以看做数据来进行传递
  1. 三种定义函数的方式
  1. function语句形式(效率比Function构造函数形式定义函数要高)
function 函数名称(参数表){
    函数执行部分;
}
  1. 对于function语句式的函数,js解析器会优先解释(也就是说js代码不是从头到尾来解释的,而是先查找有无function,有的话就会优先就是function。等到没有function了才会从第一行开始顺序解释)
  2. 能看到局只部变量不能看到全局变量
  1. 函数直接量形式
var test2 = function(){}    要注意这是一个匿名的function(也就是说是没有名字的function)
(1)能看到局只部变量不能看到全局变量
  1. 通过Function构造函数形式定义函数
var test3 = new Function(“a”,“b”,“return a + b”) ;
一定要用双引号把参数和函数的结构体括起来(在这个例子中前面两个是参数,后面的return语句是函数的结构体)
(1)只能看到全局变量不能看到局部变量(也就是说在方法里面new相当于在方法外面new一个全局的)
4、比较三种方式的区别:

 
function语句
Function构造函数
函数直接量
兼容
完全
js1.1以上
js1.2以上版本
形式
句子
表达式
表达式
名称
有名
匿名
匿名
性质
静态
动态
静态
解析时机
优先解析
顺序解析
顺序解析
作用域
具有函数的作用域
顶级函数(顶级作用域)
具有函数作用域

  1. 顺序解析:js代码执行到那一行了会去解析
  2. 具有函数的作用域:实际上就是正常的作用域
  1. 函数的参数
  1. 函数的参数:arguments对象
arguments是表示函数的实际参数(与形参无关)
  1. callee函数(回调函数属性)
  1. arguments对象用的最多的是做递归操作
<1>arguments对象的秘密属性callee方法(相当于指针,指向的是函数自己本身)
    1. 这个属性比较奇怪,它能返回arguments对象所属的函数的引用,这相当于在自己的内部调用自己
    2. arguments.callee.length其实就是函数名.length
  1. 用法:例如检测函数传递的参数是否正确
  1. 在js中函数的参数分为形参(形式参数)和实参(实际传的参数)
  1. js的参数规定不严格(形参和实参个数不一致也不会报错)
  2. 取得形参:函数名.length
  3. 函数的实际参数:内部就是用一个数组去接收函数的实际参数(这个数组还是我们看不见的,但是可以通过内部的arguments对象去访问函数的实际参数)
<1>arguments.length访问的是实参的个数
<2>arguments[索引]访问的是实参本身
<3>arguments对象只能在函数的内部访问和使用
<4>当形参个数和实参个数相等的时候才走某个方法用if来判断一下
    if(函数名.length == arguments.length){}
  1. this
  1. this对象是在运行时基于函数的执行环境绑定的。在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象
  2. this关键字总是指代调用者(也就是说谁调用了我,我就指向谁)
  1. 两个基本的函数:call、apply
  1. 每一个函数都包含两个非继承而来的方法:call、apply。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。
  2. call、apply简单的用法是绑定一些函数(根据你传递的参数不同,它绑定的作用域也不同,this指代的对象也就不同),用于传递参数调用(也就是说call方法是用来绑定一个函数的,传递的参数就是call方法里提供的参数,然后用绑定的函数来操作这些参数。apply和call差不多,不同的地方就是apply传的是参数,但接收的是一个数组)。但事实上,它们真正强大的地方是能够扩充函数的作用域(也就是说可以绑定不同的作用域)
  3. 使用call()、apply()来扩充作用域的最大好处是对象不需要与方法有任何耦合关系(也就是说对象和方法可以没有任何的关系,变相实现了java重载的效果)
  4. 在js中有一个约定俗成的规定就是如果你的function的名字大写了,那么就是一个自定义的对象
  1. 执行环境、作用域链
  1. 执行环境定义了变量/函数有权访问的其他数据,决定了它们各自的行为(也就是说在执行环境内部定义了一些变量或者函数,它们的访问权在哪里,能不能跨环境访问一些数据)。每一个执行环境都有一个与之关联的变量对象(var obj,我们在程序中是无法访问的,它保存的是环境中定义的属性),环境中定义的所有变量和函数都保存在这个对象中。虽然我们的代码无法访问这个对象,但是解析器在处理数据时会在后台执行它。
  2. 全局执行环境(比如说<script></script>就是一个全局执行环境)是最外围的一个执行环境。根据ECMScript实现所在的宿主环境不同,表示执行环境的对象也不一样
  3. 每一个函数都有自己的执行环境。当执行流进一个函数时(当你执行一段代码流进一个函数时),函数的环境就会被推入另外一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权还给之前的执行环境。当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数有序访问(环境变量可以一层一层的向上追溯<不能向下追溯,并且不能跨层追溯,只能一层一层来>,可以访问它的上级环境<包括变量、函数>)
  1. 垃圾收集、块级作用域
  1. js有自动垃圾收集机制:离开作用域的值将被自动标记为可以回收,因此将在垃圾收集期间被删除。
(1)标记清除(主流算法):给当前不使用的值加上标记,然后回收其内存
(2)引用计数法:被引用了就计一次数
(3)垃圾收集器并不是说只要一调用它就去收集,它是不能被调用的,是内部自己定时的隔一个时间段就执行垃圾收集机制
  1. js里面没有块级作用域的概念(它是认为当整个函数执行完毕之后其内部的变量才会被回收),和C、JAVA等高级语言不同(高级语言C、JAVA中for和if都是一个块级作用域,单独是一个个体,当这个作用域被执行完之后里面的变量就被释放被回收了),所以在使用if、for的时候要格外小心
  2. js模拟块级作用域
  1. js里面有一个非常好用的运算符:() 表示执行
在全局范围内部如果想要动态的执行一段函数的话,就用()把该函数括起来当做一个单独的作用域,后面再加一个(); 表示立即执行,这样一来当程序执行的时候直接就会运行该函数,并且在该作用域外就不能再访问里面的内容了
(function(){    //写一个匿名的函数
   for (vari = 0;i <= 5;i++) {        //if
       alert(i);
   }
})();
这样就达到了一个块级作用域的效果
  1. 闭包Closure
  1. 概念
  1. 闭包与函数有着紧密的关系,它是函数的代码在运行过程中的一个动态环境,是一个运行期的、动态的概念
  2. 闭包是指词法表示包括不必计算的变量的函数。也就是说该函数能够使用函数外定义的变量(就是一个函数可以访问另外一个函数作用域中的变量)
<1>封闭性:类似java中的private,起到一个保护变量的作用(也就是说当一个变量被标记为没有被使用的时候不会被回收,依旧可以在下一级作用域中被访问并且又被标记为被使用)
  1. 在程序语言中,闭包是指语法域位于某个特定的区域,具有持续参照(读写)位于该区域内自身范围之外的执行域上的非持久型变量值能力的段落。这些外部执行域的非持久型变量保留它们在闭包最初定义/创建时的值