递归:函数内部自己调用自己
导引例子 多层循环遍历数组
//test.js
var kkb=['个人介绍','工作记录',['css','html',[1,2,3]]];
//var newArr=['个人介绍','工作记录','css','html',1,2,3];
var newArr=[];
/* 数组扁平化: 把多层嵌套的数值中的内容都取出, 变成一维的数组*/
//console.log(kkb.length);
for(var i=0;i<kkb.length;i++){
if(Array.isArray(kkb[i])){
console.log('是数组');
for(var k=0;k<kkb[i].length;k++){
if(Array.isArray(kkb[i][k])){
console.log('是数组');
for(var j=0; j<kkb[i][k].length;j++){
if(Array.isArray(kkb[i][k][j])){
console.log('是数组');
}else{
console.log('不是数组');
newArr.push(kkb[i][k][j]);
}
}
}else{
console.log('不是数组');
newArr.push(kkb[i][k]);
}
}
}else{
console.log('不是数组');
//往newArr数组添加数组元素
newArr.push(kkb[i]);
}
}
console.log(newArr);//(7) ["个人介绍", "工作记录", "css", "html", 1, 2, 3]
//递归
//function fn(){
//fn();
/}
简化(封装) 多层循环遍历数组元素
var kkb=['个人介绍','工作记录',['css','html',[1,2,3]]];
//var newArr=['个人介绍','工作记录','css','html',1,2,3];
var newArr=[];
//调用
falt(kkb);
function falt(arr){
for(var i=0;i<arr.length;i++){
if(Array.isArray(arr[i])){
console.log('是数组');
falt(arr[i]);
}else{
console.log('不是数组');
//往newArr数组添加数组元素
newArr.push(arr[i]);
}
}
}
/*
第一次循环['个人介绍','工作记录',[]]
第二次循环['css','html',[]];
第三次循环[1,2,3]
falt(kkb);
falt(['css','html',[]])
falt([1,2,3])
*/
console.log(newArr);//(7) ["个人介绍", "工作记录", "css", "html", 1, 2, 3]
递归的执行流程
/*准备一个变量,初始值为0 ,然后在递归中 打印它0-5的值*/
var num=0;
function loop(num){
if(num<5){
loop(num+1);
}
console.log(num);
}
/* 先递后归 5 4 3 2 1*/
栈
- 数据存储结构 这些数据都被放在内存中
- 特点: 先进后出
- 案例 餐厅洗盘子,总是把刚洗好的放在最上面,最先放的在最下面。 取盘子的时候,从最上往下拿取。(后进先出)
- 这里我们用于存储函数调用的记录,但是栈的大小并非无限的,过多的内容导致严重的性能问题,甚至栈溢出
内存
- 存储数据的地方,但是不同的数据需要以不一样的形式进行存储。
递归的优化----尾递归
尾调用
- 在一个函数执行的最后一步,是调用函数
function fn(){
console.log(1);
fn1();
}
以下情况不属于尾调用
function fn(){
fn1();
console.log(1);//这是最后执行的
}
function fn(){
return fn1()+1;//最后一个执行的是:拿到fn1的返回值之后+1
}
尾调用不一定需要出现在代码最后,必须是最后一个执行的
function fn(){
if(true){
fn1();
}else{
fn2();
}
}
尾调用优化原理
函数执行的时候,会生成一个 ‘调用记录’以栈的数据形式存放到内存中。多了以后就会产生溢出问题,我们可以利用尾调用优化。
此处有图
利用尾调用优化后的的栈存储
此处有图
- 栈内只会存在当前函数的"调用记录",由于尾调用是最后一步,后续不在用到当前函数内的变量,位置等信息,所以可以销毁。
尾递归
- 一个函数的执行的最后一步,是调用自己本身
阶乘案例 :1 * 2 * 3 * 4 * 5
//普通递归
function fn(n){
if(n===1){
return 1;
}
return n*fn(n-1);
}
//尾递归
function fn(n,total){
if(n===1){
return toal;
}
return fn(n-1,n*total);
}
//es6才实现了尾递归优化,但是必须在严格模式下