函数
基本概念
- 函数的概念:函数就是把完成特定功能的一段代码抽取出来,使之成为程序中的一个独立实体,起个名字(函数名)。可以再同一个程序或其他程序中多次重复使用。(通过函数名调用)
- 函数的功能:可以封装任意多条语句,而且可以在任何时候调用执行。(封装函数时,函数名=标识符,要体现出函数的功能)
- 函数的作用:使程序变得简短清晰;有利于程序的维护;提高开发效率;提高代码的重用性。
- 函数的分类:
- 内置函数(系统函数、官方函数)如:alert( ) parseInt( );
- 自定义函数(用户更具实际需求,自己封装一个函数。
形参:把函数中不确定的值当做形参(形式上的参数)进行声明。
- 声明函数
function 函数名 ( ){
函数体;
}
调用函数
函数名(); - 函数体内,外面怎么写JS代码,里面就怎么写。
- 执行程序时,程序被CPU所执行。
- 函数的声明,就相当于写说明书。
- 函数调用的时候,相当于告诉CPU,请翻到某页进行执行。
- 有参函数:
function 函数名(n){
函数体;
}
函数名(10);
调用时,实参要给形参进行赋值(n为形参,10为实参) - arguments的使用(实参列表):
计算传入参数的和,具体传入多少参数不确定时,使用arguments。 -
在每个函数内,都有一个内置的数组,是一个变量,叫做arguments,可存储当前函数传入的所用参数,而且通过传参的顺序进行排列的。
arguments.length 输入传入参数的个数。
访问arguments里面的数据,需要通过对应的下标进行访问。arguments[i];
下标可以配合进行循环使用。
函数声明和函数表达式声明的区别
先上一组正常的代码
如果同时把
console.log()
移到顶端,第一个函数得到的结果不变,而第二个则会报错。由于JS解析语句时,会把当前作用域的函数声明提前到整个作用域的最前面,而函数表达式不能提前,系统无法找到result函数,自然无法输出结果。
匿名函数
回调函数
如果把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,则称为回调函数。(多用于递归,比如经典的斐波那契数列)
作用域
- 块级作用域:任何一对花括号中的语句都属于一个块,在这中定义的所有变量在代码块 外都是不可见的(JS中,只有函数有块级作用域的概念)
- 全局变量:在函数外声明的变量是全局变量,均可访问到。
- 局部变量:在函数内部使用var声明的变量,只能在函数内部访问,变量的作用域是局部的。
从上面代码中可以看出,局部作用域内可以访问到全局变量,但是外部作用域无法访问局部变量。所谓的局部变量,在JS中指的仅是函数花括号内声明的变量,而其他数据类型则没有块级作用域的概念。
注意:
- 不使用var声明的变量是全局变量,不推荐使用。
- 局部变量退出作用域之后就会被销毁,全局变量退出网页或浏览器后才被销毁。
可以在不同的函数中使用名称相同的局部变量,因为只有声明过该变量的函数才能识别出该变量。
只要函数运行完毕,本地变量就会被删除。
作用域链
[scope]:每个函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,[[scope]]就是其中一个。[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。
作用域链:[scope]中储存了呈链式结构的执行期上下文的集合,称其为作用域链。我们可以沿着作用域顶端依次向下查找变量。
执行期上下文:在函数执行前的那一刻,系统会创建执行期上下文的对象,当函数执行完毕,该执行期上下文被销毁。
具体过程为:
当函数执行前,函数会产生一个自己的执行期上下文,该执行期上下文会放到自己函数作用域的顶端,数字表示作用域链的顺序,函数可以沿着作用域链从顶端到下依次查找。
变量提升
1、解析:当局部内有相应的变量时,系统会在局部作用域内进行解析,如果局部内没有对应的变量,系统会沿着作用域链进行寻找。
此段代码中变量a虽然在全局内有声明,但是函数内部也有声明,因此优先执行函数内部的。
执行时系统自动将var a;
提前,因此a的输出值为undefined。
2、
解析:函数声明的整体都会提前,因此优先输出,里面的变量b,c属于全局变量,而a属于局部变量,因此在全局中无法输出,会报错。
js执行三步曲
- 语法步骤:先通篇扫描,但不执行
- 预编译:函数声明整体提升;变量声明部分提升(优先执行)
- 解释执行
局部预编译的四部曲(预编译发生在函数执行前一刻)
- 创建AO对象(执行期上下文)
var a=123;===>window.a=123;
- 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
- 将实参值和形参统一
- 在函数体里面找函数声明,值赋予函数体。
全局预编译的三部曲
- 生成GO对象(window)
- 找形参和变量声明,将变量和形参名作为GO属性名,值为undefined
- 在函数体里面找函数声明,值赋予函数体。
任何全局变量都归window所有。
未经声明的变量,都在GO中进行预编译。
- imply global 暗示全局变量:任何变量,如果未经声明就赋值,此变量就为全局对象(window)所有。
a = 10; ===> windows.a = 10;
- 一切声明的全局变量,全是window的属性。
var a = 123; ===> window.a = 123;
网友评论