回调函数与设计模式
Contents
- 参数的定义
return
的基本使用- 单例模式/工厂模式/桥接模式
- 回调函数的概念
参数:
局部变量
形参、实参
如果实参数量小于形参数量,那么最后没有赋值形参是undefined。
如果形参数量小于实参数量,那么多出来的实参无法从形参上获取。
外部带入的和函数内的在不产生引用时是没有关联的
非引用类型,原变量发生改变,不影响其他变量。
两个变量引用同一个地址,其中改变一个属性值,另一个也发生变化;其中改变引用地址后,另一个无关。
ES5中形参不能设置初始值,ES6中形参可以设置初始值。
形参初始值,当实参没有传入对应的值,默认是形参初始值(实参是undefined);如果传入值则是传入的值。
必要的形参定义在函数的前面,非必要的形参定义在后面,大多数的初始值都是针对非必要形参。
因为JS是弱引用类型,所以参数是不需要设置类型的
如果封装的函数被别人使用时,别人传入的参数不一定类型相同,会造成函数不可预期的错误。
回调:
1 2 3 4 5 6 7
function fn1(fn){ fn(); } function fn2(){ console.log("aaa"); } fn1(fn2);
1 2 3 4
function fn1(fn){ fn(); } fn(function(){})
当传入的参数数量不定时,
ES6:都会被放在
arg
数组中1 2 3 4
function fn1(...arg){ console,log(arg); } fn1(1,2,3,4,5);
...arg
必须放在形参后面1 2 3
function fn1(fn,...arg){ console,log(arg); }
ES5:
arguments
实参列表1 2 3 4 5 6 7 8 9
function fn1(){ var s=0; for(var i=0;i<arguments.length;i++){ s+=arguments[i]; } return s; } var sum=fn1(1,2,3,4,5,6); console.log(sum);
arguments.length
在函数内时当前函数传入的实参数量1 2 3 4 5 6
function fn1(){ console.log(arguments.length); } fn1(1,2,3,4,5,6); //arguments.length 在函数内是当前函数传入的实参数量 //console.log(fn1.length); 通过获取函数的length可以获取到函数的形参数量
通过获取函数的length可以获取到函数的形参数量
1 2 3 4 5 6 7 8 9 10
function fn1(){ console.log(arguments.callee); console.log(arguments.callee.name); console.log(arguments.callee.caller); } function fn2(){ fn1(); } fn2(); fn1();
arguments.callee
就是当前函数arguments.callee.name
就是当前函数的名字arguments.callee.caller
调用当前函数的上下文函数。
递归:
匿名递归:
1 2 3 4 5 6 7 8 9
function fn1(fn){ fn(0); } fn1(function(a){ a++; console.log(a); if(a>3) return; arguments.callee(a); })
return:
1 2 3 4 5 6
function fn1(){ var a=1; return; console.log(a); } fn1();
遇到return,跳出函数,不再执行后面的语句
1 2 3 4 5 6 7
function fn1(a){ if(!a) return; var s=a+5; console.log(s); } fn1(5);//5 fn1();//直接跳出
限定函数传入的参数类型或者其值的范围,来判断是否继续执行该函数还是跳出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
var arr=["零","一","二","三","四","五","六","七","八","九","十"]; //6 六; function getChineseNum(n){ if(n>1000) return; if(n<11) return arr[n]; if(n<20) return "十"+arr[n%10]; if(n%10===0 && n<100) return arr[n/10]+"十"; if(n<100) return arr[parseInt(n/10)]+"十"+arr[n%10]; if(n%100===0) return arr[n/100]+"百"; if(n%10===0) return arr[parseInt(n/100)]+"百"+arr[n/10%10]+"十"; if(parseInt(n/10)%10===0) return arr[parseInt(n/100)]+"百零"+arr[n%10]; return arr[parseInt(n/100)]+"百"+arr[parseInt(n/10)%10]+"十"+arr[n%10] } var str=getChineseNum(255); console.log(str);
1 2 3 4 5 6 7 8 9 10 11 12
function getSum(){ switch(type){ case "+": for(var i=1;i<arguments.length;i++)s+=argumrnts[i]; return s; case "-": case "*": case "/": } } var s=getSum("+",5,6,7); console.log(s);
求和问题(return/break)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
function getSum(type){ var s; switch(type){ case "+": s=arguments[1]; for(var i=2;i<arguments.length;i++)s+=arguments[i]; return s; case "-": s=arguments[1]; for(var i=2;i<arguments.length;i++)s-=arguments[i]; return s; case "*": s=arguments[1]; for(var i=2;i<arguments.length;i++)s*=arguments[i]; return s; case "/": s=arguments[1]; for(var i=2;i<arguments.length;i++)s/=arguments[i]; return s; } }
return
跳出函数,直接从循环中跳出函数break
跳出循环,执行循环后面的语句点击运行:
1 2 3 4 5 6 7 8 9 10 11
var bool=false; var x=0; var div1=document.getElementById("div1"); div1.onclick=function(){ bool=!bool; } setInterval(function(){ if(!bool) return; x++; div1.style.left=x+"px"; },16);
return
返回结果单例模式=====>登录弹框、遮罩层
1 2 3 4 5 6 7 8 9 10 11
var o; //function fn1(){ // return 0 || (o={}); //} function fn1(){ if(!o)o={}; return o; } var a=fn1(); var b=fn1(); console.log(a==b);
工厂模式
对象的属性名如果和值的变量名相同,可以直接带入
1 2 3 4 5 6 7 8 9 10 11 12
function fn1(name,age,sex){ return { name:name, age:age, sex:sex } } function fn1(name,age,sex){ return {name,age,sex}; } var o=fn1("ankang",22,"男"); console.log(o);
返回多个数据
1 2 3 4 5 6 7
function fn1(a,b){ a++; b*=2; return [a,b]; } var o=fn1(3,5); console.log(o);
闭包
1 2 3 4 5 6 7 8
function fn1(a){ return function(b){ console.log("aaa"); } } //var f=fn1(); //f(); fn1(3)(4);
返回回调函数的返回结果
1 2 3 4 5 6 7 8
function fn1(a,fn){ a++; return fn(a); } var s=fn1(5,function(n){ return n*2 ;}); console.log(s);
桥接模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
function fn1(){ var fn=arguments[arguments.length-1]; var s=arguments[0]; for(var i=1;i<arguments.length-1;i++){ s=fn(s,arguments[i]); } return s; } var s=fn1(1,2,3,4,5,6,function(s,n){ return s+n; }) //var s=fn1(1,2,3,4,5,6,function(){ // return s*n; //}) console.log(s);
1 2 3 4 5 6 7
function fn1(){ var a=1; var b=2 return a+b; } var s=fn1(); console.log(s);
使用return 返回一个运行结果,或者一个值,仅能返回一个;返回的结果可以在函数执行时赋值给变量。
对象中的函数
只有写在对象方法中的this,才指向当前对
写在对象属性中的this,是指向当前所在的上下文环境中this指向。
1 2 3 4 5 6 7 8 9 10 11 12
var obj={ a:1, b:2, c:function(){ console.log(obj.a);//10 consoloe.log(this.a);//1 } } var o = obj; obj={a:5}; console.log(o.a);//1 o.c();
连缀:
通过return this,来让对象中的方法可以实现连缀。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
var obj={ a:1; run:function(){ console.log("run"); console.log(this);//这里的this,打印obj这个对象===>所以返回this,即返回obj这个对象。 return this; }, play:function(){ console.log("play"); return this; } } obj.run(); obj.play(); obj.run().play(); obj.play().run();
回调函数:
|
|
将一个函数以参数的形式传入到另一个函数中并且被调用执行
目的就是不需要关注要执行谁,只负责执行。
通过插入不同的函数,解决不同的问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
function fn1(a,b,fn){ return fn(a,b); } function fn2(a,b){ return a+b; } function fn3(a,b){ return a-b; } function fn4(a,b){ return a*b; } function fn5(a,b){ return a/b; } var s=fn1(3,5,fn5); console.log(s);
var ids=setInterval(function(){},16,1,2,3);
ids=setInterval(回调函数,间隔时间,参数1,参数2…)
1 2 3 4
var ids2=setInterval(function(){ console.log("aaa")//打印一次后,被解除,不再定时执行 clearInterval(ids2) },10)
ids就是这个时间间隔标识id,可以通过clearInterval(ids)解除当前时间间隔设定
回调函数会被在间隔时间达到时调用,参数1,参数2就是向回调函数传参的方式。
时间间隔如果设置为0,或者不设置,则默认为1毫秒后。
瞬间执行完的循环是同步的,而延迟执行的是异步的,在异步执行时,同步时的变量可能早就变化了。
clearInterval()
var ids=setTimeout(function(){clearTimeout(ids)},1000,10)
延迟1000毫秒后执行这个回调函数,只执行一次。
用setTimeout重构setInterval
1 2 3 4 5 6 7 8 9
function setInterval_1(fn,time){ setTimeout(function(n){ fn(n); setInterval_1(fn,time,n) },time,arguments[2]) } setInterval_1(function(n){ console.log(n); },1000,"定时内容")
异步回调使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
function redColor(fn1,fn2){ var ids=setTimeout(function(){ console.log("红色") clearTimeout(ids); fn1(fn2,redColor); },2000); } function yellowColor(fn1,fn2){ var ids=setTimeout(function(){ console.log("黄色") clearTimeout(ids); fn1(fn2,yellowColor); },2000); } function yellowColor(fn1,fn2){ var ids=setTimeout(function(){ console.log("绿色") clearTimeout(ids); fn1(fn2,greenColor); },2000); } redColor(yellowColor,greenColor);
回调函数:
1 2 3 4 5 6 7 8 9 10 11 12
function fn1(fn,n){ if(n===undefined)n=0; n++; return fn(fn1,n); } function fn2(fn,n){ n++; if(n===10) return n; return fn(fn2,n); } var s=fn1(fn2); console.log(s);//想要的结果是10,通过回调函数实现。
Author Ankang
LastMod 2021-03-19