函数:函数就是一个工具,通过一小段代码块,完成某个功能。
函数的好处:
①可以实现函数的复用,减少了代码的编写(也可以理解为是重复使用的意思);
② 便于以后的修改和维护;
③控制执行的时机(随调随用);
定义一个函数:
①function 函数名(){
执行语句
} //函数名的规范和变量的命名规范一样;
②var 变量名 = function(){
执行语句
}
函数的调用:函数名();
①的调用可以在任意位置,是全局的;
②的调用只能在函数的下面,先定义再使用。
系统函数有:alert(), prompt()等
形参:
①出现在函数的定义部分;
②形参必须是变量;
③多余的形参的值是undefined.
实参:
①出现在函数调用部分;
②实参可以是常量、变量、表达式但是必须有值;
③多余的实参会自动舍弃。
注:参数的传递是从实参向形参传递(把实参的值传递给形参)一 一对应。
return:(将函数的结果返回)
当一个函数的结果还有其他用处时,可以将这个结果返回。
①一个函数如果遇到return,return后面的语句不执行;
②一个函数如果没有返回值,函数的返回值默认为undefined;
③一个函数如果有返回值,函数的返回值只能有一个。(也就是只能有一个return,不是只能返回一个值)
arguments:(当实参不确定时,形参不知定义多少个时,用arguments去接收实参)
①arguments只能在函数体内部使用,是函数内部自带的一个对象;
②arguments代表的是实参副本,存储了所有的实参;
③arguments长得和数组很像,但是不是真正的数组,叫类数组(伪数组);
④有下标,下标从0开始;通过[下标]去访问,获取下标对应的值:arguments[下标];
⑤arguments.length代表实参的个数(常用这来判断传入的参数的个数);
作用域:变量可访问的范围(起作用的范围)
1、全局作用域:全局变量;
①在函数外部定义的变量;
②在函数内部没有用var定义的变量;
③全局变量的作用范围是:整个程序,从全局变量的声明开始到程序结束,变量均有效。
2、局部作用域:(私有作用域)局部变量:
①在函数内部明确通过var定义的变量;
②局部变量的作用范围为函数体内部,函数调用完成后,变量自动就销毁来节省内存空间;
③所有的形参都是局部变量
顺便说一下作用域链:
其实就是作用域集合,从当前作用域到父级作用域再依次往上到全局作用域,形成的一条作用域链条。
作用域链的特点是:全局作用域的变量和方法大家都可以用(局部也可以访问),局部的变量和方法只能局部的用(闭包除外);
js的预编译和执行:(变量,函数提升的原理)
JS并不会完全按照代码顺序进行解析执行,而是在解析之前进行一次“预编译”;
JS加载包含预编译和执行两个阶段;
首先,js会把var声明和function定义声明提升到当前js的最上方,赋值语句不会被提升;(预编译)
然后代码从上往下执行。(执行)
变量提升(预解析):
JS引擎在执行的时候,会把函数和所有变量的声明都提升到当前作用域的最上面;
在js代码执行之前,浏览器的解析器在遇到var变量名和function整个函数会将其提升到当前作用域的最前面;
函数在全局作用下会变量提升,但是函数里的变量不会变量提升;只有在函数执行的时候,函数里面才会变量提升,并且遵循以下几点:
①形参赋值;
②变量提升;
③代码从上到下执行。
函数名相同时,后面的函数会把前面的函数给覆盖;
变量提升时,如果变量和函数同名,则保留函数(变量和函数的声明都会提升,但是在后面输出的值是函数的值);
函数的递归调用:
递归调用:其实就是函数自己调用自己;
递归的本质:循环;
function fac(n){ //任意一个数的阶乘 n 初始值
if(n == 1){
//条件 终值;
return 1;
}else{
return n * fac(n - 1) //n-1为步长
}
}
递归优点:代码简洁明了,容易验证正确性;
递归缺点:会进行较多次的函数调用,如果调用的层数深,每次调用时都会创建新的变量,也就会增加额外的堆栈处理,对执行效率会有一定的影响以及占用过多内存。
(递归和循环的区别)
相比较来说循环会好些:
循环的优点:速度快,结构简单;
循环的缺点:不是全能的,有的问题是适合于递归的;如果使用循环不会显得复杂的话,首先用循环。