带参函数,函数返回值,闭包

1.1 函数的定义与调用

函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块

定义:
function 函数名(){
        函数体(一坨需要重复使用的代码);
};
调用:
函数名();

//Ex1:求两个数的和
function getSum(){
	var num1=parseInt(prompt('请输入一个数字'));
	var num2=parseInt(prompt('请再输入一个数字'));
	var sum=num1+num2;
	console.log(sum);
};
getSum();

1.2 函数的注意点:

1.函数需要定义,然后才能调用;
2.函数命名:跟变量名遵循一个规则,有语义,驼峰命名法;
3.函数如果重名,后面的会把前面的覆盖;
4.不要占用本身内置方法;
5.一个函数最好是只有一个功能,有多个功能会导致不太灵活;

//不要重名
function f1(){
    console.log("haha")
}
window.f1();

//不要占用内置方法
window.setInterval(function(){
    console.log("gaga")
},1000)

1.3 函数的参数

概念:
1.3.1 在函数定义的时候,函数名后面的小括号里的变量,就是形式参数(形参);
1.3.2 在函数调用的时候,函数名后面的小括号里的变量(或者具体值都可以),就是实际参数(实参);
1.3.3 在函数调用的时候,按照规则给变量赋值,就叫传值,实参把这个值传到了形参中,就是传参;
1.3.4 实参和形参的个数可以不一样;
         如果实参个数大于形参个数,实参就有多余的,对结果没什么影响;
         如果实参个数小于形参个数,那么形参就会出现未被传参的状态,就是undefined;

//Ex1:求两个数的和
function getSum(x,y){
    var sum=x+y;
    console.log(sum);
};
var num1=parseInt(prompt('请输入一个数字'));
var num2=parseInt(prompt('请输入一个数字'));
getSum(num1,num2);

1.4 函数返回值

函数的返回值:
1.在函数内部有return关键字,并且在关键字的后面有内容(表达式或变量或具体值),那么这个内容就是函数的返回值;
2.在这个函数被调用之后,定义变量进行接收,然后我们就可以对这个包含函数返回值的变量进行常规的操作;

返回值的问题点:
1.如果一个函数有return关键字,并且明确的定义了内容,那么就有返回值;
2.如果一个函数没有return关键字,那么没有返回值;
3.如果一个函数有return关键字,但是没有定义内容,那么也没有返回值;
4.包含return关键字的函数体,函数内部后面的代码不执行;

//Ex1:最简单的带返回值的函数
function getSum(x,y,z){
    var sum=x+y+z;			
    return sum;		   
};
var result=getSum(10,20);   //定义变量接收函数的返回值
console.log(result);		//输出变量

//Ex2:求1-n之间所有数的和,函数调用的时候给n赋值为100;
function getSum(n){
    var sum=0;
    for(var i=0;i<=n;i++){
        sum+=i;
    };
    return sum;
};
var degree=parseInt(prompt('输入一个数字'));
var result=getSum(degree);
console.log(result);

//Ex3:求圆的面积//π*r*r
function getCircleArea(r){
    return Math.PI * r * r;
};
var result=getCircleArea(5);
console.log(Math.PI);
console.log(result);

//Ex4:求一个数组的最大值,最小值以及数组所有数的和;
function getMaxNum(arr){
    var maxNum=0;
    var minNum=0;
    var sumNum=0;
    for(var i=0;i<arr.length;i++){
        if (maxNum<arr[i]) {
            maxNum=arr[i];
        };
        if (minNum>arr[i]) {
            minNum=arr[i];
        };
            sumNum+=arr[i];
    };
    var newArr=[maxNum,minNum,sumNum];
    return newArr;
};
var result=getMaxNum([1000,222,3,4,5]);
console.log(result);
console.log("这个数组的最大值是:"+result[0]);
console.log("这个数组的最小值是:"+result[1]);
console.log("这个数组的和是:"+result[2]);

1.5 高阶函数

1.5.1 函数作为参数使用

//Ex1:基础例子
function f1(fn){
    console.log("这是f1函数输出的");
    fn();
};
//传入匿名函数
// f1(function(){
// 	console.log("这是匿名函数输出的");
// });
//传入命名函数
function f2(){
	console.log("这是f2函数输出的");
};
f1(f2);

//Ex2:数组sort方法的完善
var arr=[10,100,20,300,40,50,120,1];
function getSort(obj1,obj2){
	if (obj1>obj2) {
		return 1;
	}else if(obj1=obj2){
		return 0;
	}else{
		return -1;
	};
}
arr.sort(getSort);
console.log(arr);

//Ex3:定时器中传入函数(函数作为参数使用)
function f1(fn){
	var i=0;
	var timeId=setInterval(function(){
		i++;
		console.log("你好");
		if (i==5) {
			fn();
		};
		console.log("再见");
	},1000);
	window.timeId=timeId;
};
f1(function(){
	// var i=100;
	clearInterval(timeId);                   
});

1.5.2 函数作为返回值使用

Ex1:基础例子
function f1(){
	console.log("我是f1函数输出的");
	return function(){
		console.log("我是返回值里的函数输出的")
	};
};
var ff=f1();
// console.log(ff);
ff();

Ex2:三部电影  电影文件有名字,有大小,有电影上映时间
function Movie(name,size,time){
		this.name=name;
		this.size=size;
		this.time=time;
	};
	var f1=new Movie("jack&rose.avi","2000M","2007-12-1");
	var f2=new Movie("kack&rose.avi","8000M","2017-12-1");
	var f3=new Movie("lack&rose.avi","4000M","1997-12-1");
	var arr=[f1,f2,f3];
	function fn(attr){
		return function getSort(obj1,obj2){
			if (obj1[attr]>obj2[attr]) {
				return 1;
			}else if(obj1[attr]==obj2[attr]){
				return 0;
			}else{
				return -1;
			};
		};
	};
	var ff=fn("name");
	arr.sort(ff);
	for(var i=0;i<arr.length;i++){
		console.log(arr[i].name+"==="+arr[i].size+"==="+arr[i].time);
	};

1.6 闭包

1.6.1 函数作用域

全局变量    声明的变量是var声明的,并且不是在函数中声明的,就是全局变量;
局部变量    在函数中var声明的变量,就是局部变量,作用域外部不能使用
全局作用域    全局变量的作用范围
局部作用域   局部变量的作用范围
块级作用域:
 一对大括号{  },看成是一块,在这块大括号里使用的变量,就是该变量的作用范围;
在js里除了函数以外,没有块级作用域;
作用域链:
变量的使用,从里找到外,层层搜索,搜索到了就可以使用,搜索不到就报错;
预解析:
 在浏览器解析代码之前,把变量的声明和函数的声明提前,到作用域的最上面;

1.6.2闭包

当一个函数的返回值是另外一个函数,而返回的那个函数如果调用了其父函数内部的其他变量,如果返回的这个函数在外部被执行了,就产生了闭包;
闭包的作用及好处:
闭包给访问外部函数定义的内部变量创造了条件,也将关于函数的一切封闭到了函数内部,减少了全局变量,这就是闭包的好处及真实意义,其实就是缓存了数据,变相的延长了作用域;
闭包的坏处:
缓存数据;
闭包的模式:
函数模式的闭包对象模式的闭包;
//如果想要缓存数据,就把变量放在外部函数与内部函数之间;

Ex1:看看普通函数与闭包的形式有何不同

function showRandom(){

         var num=parseInt(Math.random()*11);

         console.log(num);

};

showRandom();      

showRandom();

showRandom();

//产生的是三个随机数


//闭包的方式,产生随机数

function f1(){

         var num=parseInt(Math.random()*11);

         return function(){

                  console.log(num);

         };

};

var ff=f1();

ff();

ff();

ff();         

产生了一个随机数,缓存起来了,然后被输出了三次;

如果这里不是return 而是一个命名函数,调用三次就是三次不同的结果;



Ex2:看看一个简单的执行环境

function f1(x){

         return function(y){

                  console.log(x+y);

         };

};

var fn1=f1(5);

var fn2=f1(10);

fn1(10);              //15

fn2(20);                          //30



Ex3:点赞的应用

//初始不用闭包的会出现问题

var btnObjs=document.getElementsByTagName("input");

  var value=2;

  //循环遍历每个按钮,注册点击事件

  for(var i=0;i<btnObjs.length;i++){

    //注册事件

    btnObjs[i].onclick=function (){

     

      this.value="赞("+(value++)+")";

    }

  }


//加上利用闭包缓存数据

//获取所有的按钮

  var btnObjs=document.getElementsByTagName("input");

  // 闭包缓存数据

  function getvalue(){

    var num=1;

    return function(){

      this.value="赞("+(++num)+")";

    }

  }

  //循环遍历每个按钮,注册点击事件

  for(var i=0;i<btnObjs.length;i++){

    //注册事件

    btnObjs[i].onclick=getvalue();

  }

猜你喜欢

转载自blog.csdn.net/acheng_y/article/details/81274117
今日推荐