JavaScript(第五天)—爱创课堂专业前端培训

一、递归函数
函数内部调用函数本身;

如果函数一直自己调用自己,那么就成了死循环。程序就会造成内存堆栈溢出,终止程序;

所以,递归函数一定要给一个条件,来跳出函数。

递归一般用来解决数学问题;

一般是大于0的自然数的处理!!!

如:求阶乘 5!=54321

// fn();
// function fn() {
// fn();
// }
//Uncaught RangeError: Maximum call stack size exceeded

//求阶乘 5!=54321
console.log(jieCheng(5));

//累乘法
// function jieCheng(num) {
// var result = 1;
// for (var i = 5; i > 0; i–) {
// result *= i;
// }
// return result;
// }

//递归函数法
function jieCheng(n) {
if(n === 1){
return 1;
}
return n * jieCheng(n-1);
}
/*

  • 函数调用,传参5
  • 返回:5 * jieCheng(5-1) = 5 * 4 * jieCheng(4-1) = 5 * 4 * 3 * jieCheng(3-1)
  •                     = 5 * 4 * 3 * 2 * jieCheng(2-1)
    
  •                     = 5 * 4 * 3 * 2 * 1
    
  •                     = 120
    
  • */

1

求斐波那契数列 1,1,2,3,5,8,13,21,34,55……,求第N项是多少

console.log(feiBo(5));
console.log(feiBo(6));
console.log(feiBo(7));
console.log(feiBo(8));
console.log(feiBo(9));
console.log(feiBo(10));
console.log(feiBo(11));

function feiBo(n) {
if(n === 1 || n === 2){
return 1;
}
return feiBo(n-1)+feiBo(n-2);
}
/*

  • feiBo(n) = feiBo(5) = feiBo(5-1) + feBo(5-2) = feiBo(4) + feiBo(3)
  •                 = (feiBo(4-1) + FeiBo(4-2)) + (feiBo(3-1) + feiBo(3-2))
    
  •                 = (feiBo(3) + feiBo(2)) + ( feiBo(2)+feiBo(1))
    
  •                 = feiBo(3) + 2 * feiBo(2) + feiBo(1)
    
  •                 = (feiBo(3-1) + feiBo(3-2)) +  2 * 1 + 1
    
  •                 = feiBo(2) + feiBo(1) + 2 + 1
    
  •                 = 1 + 1 + 2 + 1
    
  •                 = 5
    
  • */

1

二、立即执行函数与匿名函数
立即执行函数:也叫自执行函数,IIFE函数;程序运行,函数即可自动执行;由效果对函数体进行包裹,后面一对小括号执行函数。

匿名函数:没有名字的函数

1

2 (function(形参){

//函数体

3 })(实参);

(function (a,b) {
console.log(a+b);
})(10,20);

1

注:一般自执行函数用于加载页面时,只执行一次的操作

补充:函数体除了可以使用小括号进行包裹,还可以在函数体前面加 ~ ! + -

(function (a,b) {
console.log(a+b);
})(10,20);

~function (a,b) {
console.log(a+b);
}(10,20);

!function (a,b) {
console.log(a+b);
}(10,20);

-function (a,b) {
console.log(a+b);
}(10,20);

+function (a,b) {
console.log(a+b);
}(10,20);

1

三、闭包函数
概念:一个函数可以调用另外一个函数内部的变量

提取关键字:

两个函数

局部作用域

局部变量只能在变量当前作用域内被调用,作用域外部是没有办法调用到这个变量。

那么想要访问一个函数内部的变量,就需要从这个函数内部声明一个子函数,那么这个子函数就可以任意的调用父函数中的变量了。反之,父函数却不能调用子函数中的变量。这就是js中存在的链式作用域的概念。

var str = “Hello World!!”;
console.log(fn());//ƒ fn2() {console.log(“num:”,num);}
console.log(“num:”,fn()());//num: 10
function fn() {
var num = 10;
// console.log(“num:”,num);
function fn2() {
// console.log(“num:”,num);
return num;
}
return fn2;
}
// console.log(“num:”,num);// num is not defined

1

但是,这种fn2形成的闭包函数,并不是我们所要说的。我们想要的是函数外部的函数可以调用这个函数内部的局部变量。

思考?可不可以将内部的函数作为一个桥梁,来连接内外 ,作为一个传递数据的通道

function fn() {
var num = 10;
return function () {
return num;
}
}
console.log(“fn函数:”,fn());
console.log(“fn内部匿名函数执行结果:”,fn()());

//现在想要在fn函数的外部调用fn内部的变量num,该怎么做???
var test = fn();//test 和 内部的匿名函数一样,形成一个闭包;都叫做闭包函数
console.log(“test函数:”,test);
console.log(“test函数执行结果:”,test());

1

闭包函数的特点:

观察下面代码,内部匿名函数,每一次执行,都是一次全新的开始,会形成一个新的闭包;

但是用外部变量test或test2来声明接收的fn内部匿名函数的赋值,test或test2函数会形成自己的闭包;

由于fn内部匿名函数和变量是局部的,单独执行调用时生成,调用完毕结束;

但是test或test2不同,它是一个全局变量(函数),全局就是页面生成时创建,关闭销毁;常驻内存了。

以test为例,从内存角度来讲,与fn内部的匿名函数建立了一个引用关系,而这个匿名函数又和fn内部的变量num有引用关系;在js中,有一个垃圾回收机制,只有当对象之间不存在引用关系时,才会回收。所以,test去调用的num并没有被回收,而是常驻内存,所以在我们连续执行几次test之后,num依次递增。

function fn() {
var num = 10;
return function () {
return num++;
}
}

// console.log(“fn函数:”,fn());
// console.log(“fn内部匿名函数执行结果:”,fn()());

//现在想要在fn函数的外部调用fn内部的变量num,该怎么做???
var test = fn();
var test2 = fn();
// console.log(“test函数:”,test);
// console.log(“test函数执行结果:”,test());

console.group(“fn内部的函数连续执行4次”);
console.log(“fn内部的函数第1次执行”,fn()());//10
console.log(“fn内部的函数第2次执行”,fn()());//10
console.log(“fn内部的函数第3次执行”,fn()());//10
console.log(“fn内部的函数第4次执行”,fn()());//10
console.log(“fn内部的函数每一次执行都会形成一个新的闭包”)
console.groupEnd();

console.group(“test函数连续执行4次”);
console.log(“test函数第1次执行:”,test());//10
console.log(“test函数第2次执行:”,test());//11
console.log(“test函数第3次执行:”,test());//12
console.log(“test函数第4次执行:”,test());//13
console.groupEnd();

console.log(test2());//10
console.log(test2());//11

1

闭包函数使用过多:可能会造成内存泄漏的问题,以及对全局变量造成污染。

但是在很多高级程序开发过程中,也会经常用到闭包,闭包是一个重点也是一个难点。

闭包的应用:

在循环中的应用:定时器和事件函数

求fn(3)(4)(5)(6),结果是 360

// 求fn(3)(4)(5)(6),结果是 360
console.log(fn(3)(4)(5)(6));
function fn(num1) {
return function (num2) {
return function (num3) {
return function (num4) {
return num1 * num2 * num3 * num4;
}
}
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值