JS函数、闭包、立即执行函数

JS函数

函数的定义

(1)function表示定义函数,fun为函数名,函数名必须符合JS标识符命名规则,圆括号中是形参列表,即使没有形参,也必须书写圆括号。

function fun(){
   //函数体语句
}

(2)函数表达式
也叫作匿名函数

var fun = function (){
   //函数体语句
}

函数的调用:fun()

函数声明的提升

和变量声明提升类似,函数声明也可以被提升(在预解析阶段会被提升)

   fun()
   function fun(){
        alert("函数被执行")}

注意:函数表达式不能提升。因为它相当于是一个变量,变量声明提升只提升定义,不提升值,为undefined,故会引发错误。
函数优先提升(先预解析函数,再预解析变量)(变量声明提升,无法覆盖提升的函数)

   fun();       //弹出B
   var fun = function () {
       alert("A");
   }
   function fun () {
        alert('B');
   }
   fun();       //弹出A
//运行结果为 B   A,而不是B   A   B(B在预解析阶段定义的)

函数的参数和返回值

在这里插入图片描述
遇见return即退出函数,将执行权交还给调用者
(字符串长度的获取使用属性:string.length )

函数拓展题——面试常见

善于发现一些独立的逻辑,将这些独立的逻辑封装成一个函数。
例1:喇叭花数是这样的三位数:其每一位数字的阶乘之和恰好等于它本身。即abc=a!+b!+c!,其中abc表示一个三位数。试寻找所有喇叭花数。

 // 封装求阶乘的函数
    function factorical(n) {
        var result = 1
        for (var i = 1; i <= n; i++) {
            result = result * i
        }
        return result
    }
    //寻找喇叭花数
    for (var i = 100; i <= 999; i++) {
    //a、b、c分别表示百位、十位、个位数
        var a = Number(i.toString()[0])
        var b = Number(i.toString()[1])
        var c = Number(i.toString()[2])
        // console.log(a,b,c)
        if(factorical(a)+factorical(b)+factorical(c) == i){
         console.log(i)
         }
    }

sort()方法:数组排序可以使用sort()方法,这个方法的参数又是一个函数。这个函数中的a、b分别表示数组中靠前和靠后的项,如果需要将他们交换位置,则返回任意正数,否则就返回负数。

var arr = [33,22,55,11]
arr.sort(function (a,b){
    if(a>b){
      return 1;
      }else{
          return -1;
       }
     });
     //或者可以直接return a-b;表示从小到大排列,b-a表示从大到小排列

全局变量和局部变量

JavaScript是函数级作用域编程语言:变量只在其定义时所在的function内部有意义,定义在函数内部的为局部变量。
如果不将变量定义在任何函数的内部,此时这个变量就是全局变量,他在任何函数内都可以被访问和更改。

遮蔽效应

如果函数中也定义了和全局同名的变量,则函数内的变量会将全局的变量“遮蔽”,函数内会使用自己内部定义的变量。

形参也是函数内部的局部变量

作用域链

函数的嵌套

一个函数内部也可以定义一个函数,和局部变量类似,定义在一个函数内部的函数是局部函数。

作用域链

在函数嵌套中,变量会从内到外逐层寻找它的定义,从最里层开始逐层向上寻找。
在这里插入图片描述
在初次给变量赋值时,如果没有加var,则将定义全局变量

注意变量声明提升的情况(重要)

   var a=10
   function fun(){
    //注意JS有一个预解析的过程,所以在函数内部会与解析到函数内部的a
    // 将函数内部定义的a提升到a++的前面,根据“遮蔽效应”,函数内部的变量a会将全局的a遮蔽掉
    // 变量声明提升只提升定义不提升值,故a++是对undefined自增1,结果为NaN
    // 自增完后重新对a赋值为6,故函数内部打印a为6
    a++;
    var a=6;
    console.log(a)    //6
   }   
   fun();
   console.log(a)    //10

递归

1.什么是递归
函数的内部语句可以调用这个函数自身,从而发起对函数的一次迭代。在新的迭代中,又会执行调用函数自身的语句,从而又产生一次迭代。当函数执行到某一次时,不再进行新的迭代,函数被一层一层返回,函数被递归。(重复同一个工作时可以使用)
2.递归的要素
边界条件:确定递归到何时终止,也称为递归出口
递归模式:大问题是如何分解为小问题的,也称为递归体

//书写一个杉树,这个函数内部自己会调用自己,从而形成递归
function factorial(n){
   //函数的功能是计算n的阶乘,n!不就是n*(n-1)!
   //这个就是递归的出口,如果计算1的阶乘,可以不用递归了,直接答案就是1
    if(n==1)   return 1;
    //如果询问的不是1的阶乘,就返回n*(n-1)!
    return n * factorial(n-1);
}

递归常见算法题
例:斐波那契数列是这样的数列:1、1、2、3、5、8、13、21,其规律就是数列下标为0和1的项的值都是1,从下标为2的项开始,每项等于前面两项的和。

// 编写一个函数,这个函数的功能是返回斐波那契数列中下标为n的那项的值
    function fib(n) {
        // 数列下标为0的项,和下标为1的项的值都是1
        if (n == 0 || n == 1) return 1;
        // 斐波那契数列的本质特征就是每一项,都等于前面两项的和
        return fib(n - 1) + fib(n - 2)
    }
    // 书写一个循环语句,计算斐波那契数列的前15项
    for (var i = 0; i <= 14; i++) {
        console.log(fib(i))
    }

闭包(后续补充)

什么是闭包

  • JavaScript中函数会产生闭包(closure),闭包是函数本身和该函数声明时所处环境状态的组合。
  • 函数能够“记忆住”其定义时所处的环境,即使函数不在其定义的环境中被调用,也能访问定义时所处环境的变量。
    观察闭包现象
  • 在JavaScript中,每次创建函数都会创建闭包
  • 但是,闭包特性往往需要将函数“换一个地方”执行,才能被观察出来
  • 闭包很有用,因为闭包允许我们将数据与操作该数据的函数关联起来,这与面向对象编程有少许相似之处
  • 闭包的功能:记忆性、模拟私有变量
    闭包的用途
    记忆性:当闭包产生时,函数所处环境的状态会始终保持在内存中,不会在外层函数调用后被自动清除,这就是闭包的记忆性。

闭包记忆性案例

在这里插入图片描述
闭包模拟私有变量
一道面试题:fun1()和fun2()互不干扰,各自形成自己的闭包
在这里插入图片描述
闭包的一个案例
在这里插入图片描述

闭包的缺点(转)

  • 在某些情况下,闭包可能会导致内存泄露。
  • 在某些情况下,闭包可能会占用过多的内存空间,导致性能下降。
  • 闭包需要访问外部函数的变量,因此会带来一定的性能损失。

立即执行函数IIFE

1.什么是IIFE
IIFE = Immediately lnvoked Function Expression,立即调用函数表达式
是一种特殊的JavaScript写法,一旦被定义,就立即被调用

基本写法:
    (function(){
        statements
    })();
    
    //最外层括号对的功能:将函数变为表达式
    //此时该函数是一个语句体,而在js之中,语句体是不可以加圆括号直接运行的
    //所以要加圆括号,将函数变为表达式

2.形成IIFE的方法
1)函数不可以直接加圆括号被调用
2)函数必须转为“函数表达式”才能被调用(原因是前端的一种特性)

3.IIFE的作用
1)为变量赋值:可以使语法显得更为紧凑
2)可以在某些场合(例如for循环)中,将全局变量变为局部变量,使语法更为紧凑

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值