回调函数及递归
回调函数
1、回调函数是将一个函数以参数的形式传入到另一个函数中被调用执行。目的是不需要关注执行谁,只需要执行就可以。
2、通过插入不同的函数,解决不同的问题。
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);
3、桥接模式
function fn1(){
var fn=arguments[length-1];
var s=argements[0];
for(i=1;i<argements.length-1;i++){
s=fn(s,arguments[i]);
}
return s;
}
var s=fn1(1,2,3,4,5,function(s,n){
return s+n;
})
var s=fn1(1,2,3,4,5,function(s,n){
return s*n;
})
4、setInterval()
var ids=setInterval(回调函数,间隔时间,参数1,参数2…)
ids就是这个时间间隔标识ID,可以通过clearInterval(ids)解除当前时间间隔设定
回调函数会在间隔时间达到时调用,参数1,参数2就是向回调函数传参的参数
var i=0;
var ids=setInterval(function(a,b,c){
i++;
console.log(a+b+c);
if(i>3) clearInterval(ids);
},16,1,2,3)
瞬间执行完的循环是同步的,而延迟执行的setInterval是异步的,在异步执行时,同步时的变量可能早就改变了
for(var i=0;i<10;i++){
setInterval(function(n){
console.log(n);
},1000,i);
}
5、setTimeout()
//延迟1000毫秒执行这个回调函数,只执行一次
setTimeout(function(){
console.log("aaa");
},1000)
异步回调使用,按照顺序打印红黄绿
function redColor(fn1,fn2){
var ids=setTimeout(()=>{
console.log("红色");
clearTimeout(ids);
fn1(fn2,redColor);
},2000)
}
function yellowColor(fn1,fn2){
var ids=setTimeout(()=>{
console.log("黄色");
clearTimeout(ids);
fn1(fn2,yellowColor);
},2000)
}
function greenColor(fn1,fn2){
var ids=setTimeout(()=>{
console.log("绿色");
clearTimeout(ids);
fn1(fn2,greenColor);
},2000)
}
redColor(yellowColor,greenColor)
递归
1、递归就是一个函数在它的函数体内调用它自身。执行递归函数将反复调用其自身,每调用一次就进入新的一层。递归函数必须有结束条件。
注:
递归的时候,每次调用一个函数,计算机都会为这个函数分配新的空间,这就是说,当被调函数返回的时候,调用函数中的变量依然会保持原先的值,否则也不可能实现反向输出。
var i=0;
function fn(){
i++;
if(i<5) fn();
console.log(i);//最后打印
}
//因为每次递归都是在堆中建立一个新的函数,当递归次数很多时,会造成代码出现错误。
function fn1(){
i++;
if(i<12000) fn1();
console.log(i);
}
2、对象的广度遍历使用for in,对象的深度遍历使用递归
var obj={
a:1,
b:2,
c:{
a1:3,
b1:4,
c1:{
a2:5,
b2:6,
}
}
d:6,
e:function(){
console.log("aaa");
}
}
//遍历对象
function fn(o){
for(var prop in o){
console.log(prop,o[prop]);
if(typeof o[prop]==="object"&&o[prop]!==null){
fn(o[prop])
}
}
}
fn(obj);
3、对象深复制
function fn(source,target){
if(target===undefined) target={};
for(var prop in source){
if(typeof source[prop]==="object"&&source[prop]!==null){
target[prop]={};
fn(source[prop],target[prop]);
}else target[prop]=source[prop];
}
return target;
}
var o=fn(obj);
console.log(o);
4、深查找
function fn(o,value){
for(var prop in o){
if(o[prop]===value) return prop;
if(typeof o[prop]==="object"&&o[prop]!==null){
var s=fn(o[prop],value);
if(s) return s;
}
}
}
var n=fn(obj,6);
console.log(n);
5、二叉树遍历(递归方法)
var obj={
value:0,
left:{
value:1,
left:{
value:3,
},
right:{
value:4,
}
},
right:{
value:2,
left:{
value:5,
},
right:{
value:6
}
}
}
//前序遍历
function fn(o){
console.log(o.value);
if(o.left) fn(o.left);
if(o.right) fn(o.right);
}
//中序遍历
function fn(o){
if(o.left) fn(o.left);
console.log(o.value);
if(o.right) fn(o.right);
}
//后序遍历
function fn(o){
if(o.left) fn(o.left);
if(o.right) fn(o.right);
console.log(o.value);
}
6、练习一:把十进制数字转换成二进制数输出
练习二:把十进制数字转换成十六进制数输出
//二进制
function fn(n,str){
if(str===undefined) str="";
str=n%2+str;
n=parseInt(n/2);
if(n) return fn(n,str);
return str;
}
var n=fn(15);
console.log(n);
//十六进制
function fn(n,str){
if(str===undefined) str="";
str=(n%16>9?String.fromCharCode(n%16+87):n%16)+str;
n=parseInt(n/16);
if(n) return fn(n,str);
return str;
}
var n=fn(255);
console.log(n);