函数:一次定义、多次使用
一、函数语法
1.声明普通函数:function()
// 声明普通函数
function fn(){// fn 为函数名
console.log('hello Function!');
}
// 调用有名函数
fn();// 这里的圆括号运算符表示对函数的调用操作
2.匿名函数:将函数内容赋值给变量
将函数作为一个值赋值给一个变量
// 定义赋值匿名函数
var fn = function(){
console.log('hello Function!');
}
// 调用函数
fn();
二、函数四要素
- 函数名 (语法要求)
- 函数体 (函数体缺失那么该函数就是无意义的)
- 参数
形参
实参
- 返回值 (语法要求)
三、函数的参数
1.形参
//形参,函数被定义在小括号中提前预设的准备接受实参的形象参数
function func(n1, n2) {
// console.log(n1 + n2);
var sum = n1 + n2;
document.write(sum + "<br/>");
}
2.实参
函数调用时指定的参数,写在执行函数的圆括号运算符内部,有实际的值。
//实参:函数调用时在小括号中传递的实际的参数
func(1, 2);
上面的形参仅仅只是被声明了还没有赋值,实参的作用就是为形参传值的,所以它们之间的关系就相当于是在做普通的赋值操作,只不过是语法上发生了改变。
参数的顺序和个数
//函数的参数是一一对应的
//第一个参数会传递给第一个形参接收
//第二个参数会传递给第二个形参接收
//如果实参个数和形参个数不一致
//如果实参的个数 少于 形参的个数,没有接收到实参的形参值为undefined
//如果实参的个数 多于 形参的个数,没有接收到实参的形参值为undefined
四、函数的返回值
//函数必须要有返回值
//函数执行完之后必须有一个结果,这个结果叫做:返回值
//使用return关键字来执行函数的返回值。
//return后面书写的内容(必须要和return写在一行)就是返回值
//因为return具有终止函数的作用,写在return下一行的内容,都不会执行
//return后面书写的内容(必须要和return写在一行)就是返回值
function getSum(num1,num2){
return num1+num2;
}
// 函数的返回值直接赋值给一个变量
var result = getSum(10,20);
// 函数返回值直接参与运算
console.log( getSum(10,20)/5 );
//因为return具有终止函数的作用,写在return下一行
// 如果函数没有return或者return,后面没有值,在函数的的返回值就是undefined
//函数被调用的时候就是得到返回值的时候
五、变量的作用域
1.全局变量
定义在函数外部,在页面的任何位置都能正常访问的变量。
全局变量的优点
- 省心省力
- 有效的减少变量的个数(当多个函数用到同一个值一个全局变量就能搞定)
全局变量的缺点
- 变量污染:变量名之间的相互覆盖
- 增加函数之间的耦合性:函数之间相互依赖
- 内存压力:因为一直保存在内存中,即便是不需要的时候也会一直存在,不利于内存空间的合理利用
2.局部变量
定义在函数内部,只能在该函数内部访问。
3.重名
当全局变量和局部变量重名时,优先使用局部变量
如果在它们重名的情况下还想在函数中访问到全局变量:
- 在变量名前加上window前缀
- 如果该函数是全局函数也可以在变量名前加上this前缀
var num = 10;
function fn(){
var num = 20;
console.log(num);// 20
console.log(window.num);// 10
console.log(this.num);// 10
}
六、声明变量不加var
如果声明变量不加var,则声明的变量是一个全局变量
七、变量的作用域链
var num =1231;
function fn1(){
var num = 232;
console.log("num"); //
function fn2(){
var num =897";
console.log("num"); //?
function fn3(){
num=1213;
console.log("name"); //?
}
fn3();
}
fn2();
}
fn1();
在作用域链情况下:
当变量没加var时,会去在上一个作用域中找【同名&带var】
找到了 - >直接修改
找不到 - >在作用域链上找
一直找到顶级作用域
找到了 - >直接修改
找不到 - >自己创建修改
八、函数递归
递归在JS语言中的具体表现为:函数调用自身
递归的特点:重复计算执行,和循环非常类似。所以递归也和循环一样,需要一个出口(停止条件)。
例如:从1打印到100
// 循环的方法
for( var i=1;i<=100;i++ ){
console.log(i);
}
// 递归的方法
function showNum(num){
console.log(num);
if(num == 100){
return;
}
num++;
return showNum(num);// 函数内部调用自身
}
showNum(1);
递归的缺点 | 递归的优点 |
性能不如循环; 内存占用过高; 递归次数必须预期收敛; | 操作简洁; 当处理子问题与原始问题相同时,操作简单 |