js知识点梳理-Function

192 阅读5分钟

概念: Function是一段被【预定义好的】,可以【反复使用】的代码,是独立的功能体,可以放入【若干】代码

适合放在函数中的内容:

  • 不希望打开页面立即执行,等用户来触发
  • 不希望执行一次,可以反复触发
  • 本身就是一个独立的功能体
  • 函数在js中具有第一等公民的地位,函数中的变量会自动释放

注意:

  • 传入实参的顺序一定要和形参一一对应
  • 函数不一定必须传入参数
    • 若操作固定,则不需要传递参数
    • 根据传入的参数不同,做的操作也略微不同,则需要添加参数

1.创建函数

  • 声明方式:用function关键字进行声明,但只有变量/常量/函数具有声明方式
    • function 函数名(形参){函数体;return 返回值;}
    • 具有完整的声明提前
  • 直接量方式
    • var 函数名=function(形参){函数体;return 返回值;}
    • 有声明提前,但赋值留在原地
  • 构造函数方式
    • var 函数名=new Function("形参",...,"函数体")
    • 函数体在动态拼接时使用

调用函数

  • 函数名(实参);
  • var result=函数名(实参)

return

本意是退出函数,但若后面跟着一个数据,则可将数据返回到全局作用域,但仅返回并未保存,所以需要创建变量接住调用结果

  • return只能写一次,最好写在函数体后面
  • 何时使用:并不是任何时候都需要加return
    • 全局想使用局部时
    • 调用完函数还想拿到函数结果进行后续操作时
    • 若无return,会有默认返回值undefined

2.作用域

  • 全局:哪里都可以使用
  • 函数:只能在函数调用时内部使用
  • 变量的使用规则:优先使用局部,局部没有找全局,全局没有则报错

3.声明提前

在程序正式执行前,会将var声明的变量和function声明的函数集中提前到当前作用域顶部,但赋值留在原地

4.按值传递

  • 原始类型之间 互不影响
  • 引用类型之间 相互影响

5.重载

相同的函数根据传入的实参不同,会自动选择相应函数执行

  • 目的:减少程序员负担
  • 注意:js不支持重载,因为js不允许同时存在多个同名函数,最后一个会覆盖之前的所有函数

arguments

  • 函数内部使用,类数组:下标、length、遍历
  • 作用:可以借助实参,则不需要创建形参
  • 使用arguments实现重载:通过判断arguments,实现功能
//传入一个实参做乘方,传入两个实参做加法
function f1(){
    if(arguments.length==1){
        return Math.pow(arguments[0],2);
    }else if(arguments.length==2){
        return arguments[0]+arguments[1];
    }
}
console.log(f1(8));
console.log(f1(8,9);

6.匿名函数

无名字的函数,被没有变量名/函数名引用着,调用完毕后会立即释放

  • 匿名函数自调(function(){函数体;})()
  • 匿名函数回调:某个函数调用时,传入的实参是一个函数,且不需要调用执行
//例
arr.sort(function(a,b){return a-b;})
str.replace(reg,function(){})
  • 匿名函数不是自调就是回调

7.闭包

函数的执行原理

① 程序在加载时:创建执行环境栈(ECS),首先压入全局执行环境(全局EC),全局EC中引用着全局对象window,window中保存着全局变量

② 定义函数时:创建函数对象,封装函数的定义。在函数对象中创建scope属性(记录自己来自的作用域)。全局函数的scope是window

③ 调用函数前:在执行环境栈中压入新的函数EC。创建活动对象AO,保存着本次函数调用时用到的局部变量。在EC中添加scope chain属性引用AO,设置AO的parent属性为函数的scope对象

④ 调用时:变量的使用规则是有限使用局部,局部没有找全局,全局没有报错

⑤ 调用完:函数的EC会出栈,AO会自动释放,故局部变量自动释放

作用域链scope chain

  • 概念:以EC中的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构,称为作用域链
  • 作用:查找变量

闭包

  • 概念:保护一个可以【反复使用的局部变量】的一种词法结构,结合了局部和全局的优点
  • 使用步骤:
    • 创建一个外层函数
    • 在其中创建一个受保护的局部变量
    • 外层函数调用要返回内层函数,此内层函数在操作受保护的变量
  • 缺点:受保护的变量永远无法释放,用多了会导致内存泄漏
  • 闭包的重点:
    • 判断闭包,找到受保护的变量,确定其值
    • 外层函数调用几次,就创建了几个闭包,受保护的变量就有了几个副本
    • 同一外层函数调用,返回的内层函数,都是在使用同一个受保护的变量
//语法
function 外层函数(){
    受保护的变量;
    return function(){
        不断操作受保护的变量;
        return 结果;
    }
}
var 内层函数=外层函数();
  • 开发:防抖节流

    • elem.onmousemove 鼠标移动事件,每次移动都会触发
    • input.oninput input每次修改都会触发的事件
    • window.onresize 屏幕每次改变大小都会触发

    不会减少函数执行次数,但会减少DOM树渲染,DOM数据渲染的次数越频繁页面的效率越低下

//防抖节流
function fdjl(){
    var timer=null;
    return function(){
        if(timer){clearTimeout(timer)}//判断有无定时器,有则清除
        timer=setTimeout(function(){
            操作;
        },毫秒数)
    }
}
var animate=fdjl();