参数是回调函数
function fn(f){
f();
}
function fn1(){
console.log("aaa");
}
fn(fn1);
可以认为每个函数是解决一个功能的语句块,通过回调的方式完成插槽特征
桥接模式:fn起到桥梁的作用,fns不关注功能
var str = "";
function fns(fn){
for(var i = 0;i < 10;i++){
fn(i,-i);
}
}
function getSum1(n,m){
str += n + "," + m + ",";
}
function getSum2(n,m){
str += n + "|" + m + ",";
}
function getSum3(n,m){
str += n * m + ",";
}
fns(getSum1);
console.log(str);
与匿名函数写法相同
fns(function(n,m){
str += n * m +",";
})
console.log(str);
遍历循环,每一次回调
var arr = [1,2,3,4,5];
// item是数组的每个元素,index是数组下标,arr是数组
// arr.forEach(function(item,index,arr){
// console.log(item,index,arr)
// })
function forEachs(arr,fn){
for(var i = 0;i < arr.length;i++){
fn(arr[i],i,arr);
}
}
forEachs(arr,function(item,index,arr){
console.log(item,index,arr);
})
数组累加
function getValues(arr,fn){
var sum = 0;
// var len = arr.length;
for(var i = 0;i < arr.length;i++){
sum = fn(sum,arr[i],i);
}
console.log(sum);
}
getValues(arr,function(sum,item,index){
sum += item;
return sum;
})
乘积
function getValues(arr,fn){
var sum = 1;
for(var i = 0;i < arr.length;i++){
sum = fn(sum,arr[i],i);
}
console.log(sum);
}
getValues(arr,function(sum,item,index){
sum *= item;
return sum;
})
数组中奇数乘积
function getValues(arr,fn){
var sum = 1;
for(var i = 0;i < arr.length;i++){
//if(arr[i] % 2 ===0) continue;
sum = fn(sum,arr[i],i);
}
console.log(sum);
}
getValues(arr,function(sum,item,index){
if(item % 2 === 0) return sum;
sum *= item;
return sum;
})
桥接模式特征:只需要更改回调函数的内部内容就可以达到期待的内容,
放入的fn就相当于一个桥梁,并且把需要改变的部分分割出来
回调函数的作用:
1.功能语句块的分离(桥接模式)
2.完成异步执行的代码
// setInterval每隔16毫秒执行一次
// 直到清理了
setInterval(animation,16);//间隔执行
function animation(){
console.log("a");
}
function animation(m,n){
console.log(m,n);
}
// 2000毫秒后执行且只执行一次
setTimeout(animation,2000);//延迟执行
setTimeout(animation(10),2000);//会瞬间执行animation函数,由于函数没有返回值,所以返回值为undefined,,2000毫秒后什么也不执行
//如果想传参,写法如下
// 第三个参数后面是回调传参的
setTimeout(animation,2000,10,20);
回调函数不能直接传参
function fn(f){
f();
}
function fn1(n){
console.log(n);
}
fn(fn1(10));//不行
如果传参需要改为如下代码:
function fn(f,n){
f(n);
}
function fn1(n){
console.log(n);
}
fn(fn1,10);
但是不确定参数有多少个,所以以上方式比较麻烦
回调函数返回值
回调多少次就返回多少层,
setTimeout和setInterval使用回调函数时,不能return
setTimeout会返回一个ids,ids是一个数值,setTimeout未执行时是0,执行后是1;
所以执行完后需要将ids清理;
setTimeout第三个参数后面是回调传参的
clearTimeout(ids);//清理ids否则会内存泄漏
因为会清除,所以不断地回到当前位置
var ids = setTimeout(animation,2000);
function animation(){
console.log(ids);//1 2 3....
clearTimeout(ids);
ids = setTimeout(animation,1000);
}
红绿灯
var arr=["红","黄","绿"];
var i = 0;
var ids = setTimeout(animation ,2000);
function animation(){
console.log(arr[i]);
clearTimeout(ids);
i++;
ids = setTimeout(animation,1000);
}
运行结果
var arr=["红","黄","绿"];
var i = 0;
var ids = setTimeout(animation ,2000);
function animation(){
console.log(arr[i]);
clearTimeout(ids);
i++;
if(i > 2) i = 0;
ids = setTimeout(animation,1000);
}
运行结果:
不用全局变量,尽量减少全局变量的使用
var ids = setTimeout(animation ,2000,["红","黄","绿"],0);
function animation(arr,i){
console.log(arr[i]);
clearTimeout(ids);
i++;
if(i > 2) i = 0;
ids = setTimeout(animation,1000,arr,i);
}
修改时间间隔
var ids = setTimeout(animation ,2000,["红","黄","绿"],0);
function animation(arr,i){
console.log(arr[i]);
clearTimeout(ids);
i++;
if(i > 2) i = 0;
ids = setTimeout(animation,i===1?1000:2000,arr,i);
}
var ids = setTimeout(animation ,2000,["红","黄","绿"],0);
function animation(arr,i){
console.log(arr[i]);
clearTimeout(ids);
i++;
if(i > 2) i = 0;
ids = setTimeout(animation,i===0?2000:1000,arr,i);
}
红黄绿绿黄红
var ids = setTimeout(animation ,2000,["红","黄","绿"],0);
function animation(arr,i,state){
console.log(arr[i]);
clearTimeout(ids);
if(!state){
i++;
if(i>=2) state=true;
}else{
i--;
if(i<=0) state=false;
}
ids = setTimeout(animation,i===0?2000:1000,arr,i,state);
}
function showLight(){
showRed();
}
function showRed(){
var ids = setTimeout(function(){
console.log("红色");
clearTimeout(ids);
showYellow();
},2000);
}
function showYellow(){
var ids = setTimeout(function(){
console.log("黄色");
clearTimeout(ids);
showGreen();
},2000);
}
function showGreen(){
var ids = setTimeout(function(){
console.log("绿色");
clearTimeout(ids);
showRed();
},2000);
}
showLight();
代码不够灵活
function showLight(fn1,fn2,fn3){
fn1(fn2,fn3);
}
function showRed(fn1,fn2){
var ids = setTimeout(function(){
console.log("红色");
clearTimeout(ids);
fn1(fn2,showRed);
},2000);
}
function showYellow(fn1,fn2){
var ids = setTimeout(function(){
console.log("黄色");
clearTimeout(ids);
fn1(fn2,showYellow);
},2000);
}
function showGreen(fn1,fn2){
var ids = setTimeout(function(){
console.log("绿色");
clearTimeout(ids);
fn1(fn2,showGreen);
},2000);
}
showLight(showRed,showYellow,showGreen);
太绕了,但是可以通过修改实参的位置,修改颜色的打印
function showLight(){
var arr=[];
// arguments变成数组形式
for(var i=0;i<arguments.length;i++){
arr[i]=arguments[i];
}
arguments[0](arr);
}
function showRed(arr){
arr.push(arr.shift());//把第一个删除放在最后
var ids=setTimeout(function(){
console.log("红色");
clearTimeout(ids);
arr[0](arr);
},2000);
}
function showYellow(arr){
arr.push(arr.shift());//把第一个删除放在最后
var ids=setTimeout(function(){
console.log("黄色");
clearTimeout(ids);
arr[0](arr);
},2000);
}
function showGreen(arr){
arr.push(arr.shift());//把第一个删除放在最后
var ids=setTimeout(function(){
console.log("绿色");
clearTimeout(ids);
arr[0](arr);
},2000);
}
showLight(showRed,showYellow,showGreen,showRed,showGreen);
变色代码
<style>
div{
width: 100px;
height: 100px;
background-color: red;
}
</style>
var div1=document.getElementById("div1");
var color={r:255,g:0,b:0};
var state=0;
setInterval(animation,16);
function animation(){
switch(state){
case 0:
if(setColor("b",true)) state=1;
break;
case 1:
if(setColor("r",false)) state=2;
break;
case 2:
if(setColor("g",true)) state=3;
break;
case 3:
if(setColor("b",false)) state=4;
break;
case 4:
if(setColor("r",true)) state=5;
break;
case 5:
if(setColor("g",false)) state=0;
break;
}
div1.style.backgroundColor="rgb("+color.r+","+color.g+","+color.b+")";
}
function setColor(key,bool){
if(bool){
color[key]++;
if(color[key]===255) return true;
}else{
color[key]--;
if(color[key]===0) return true;
}
return false;
}
回调循环