函数

105 阅读5分钟

函数

概述

函数是抽取的公共代码块,主要是为了复用。函数相当于一个工具需要的时候就可以调用,当我们没有 这个工具就需要自己封装。

函数的分类

  • 系统函数 (console.log、 toString parseInt 等 )
  • 内置函数 (Math.pow等)
  • 自定义函数 (自己定义的函数)

函数的定义

  • 使用function关键词声明定义
匿名函数的定义(没有函数名的函数 无法被复用)
function(){
    代码块
}
具名函数的定义 (有函数名的函数 必须调用才会执行 可以复用)
function 函数名(){
    代码块
}
函数名(函数调用)
用new 关键构建函数对象(不推荐)
var 函数名 = new function(){
    代码块
} 
函数名(调用)

预编译机制

  • var关键词修饰的变量会进行预编译过程
  • function 也会进行预编译过程
  • 变量的默认值为 undefined
  • 函数的默认值 是函数本身
  • 在提升时,只提升到当前作用域的顶部
  • 当变量名和函数名重合时,只保留函数
  • 声明变量没有var,就不会进行提升 会报错
概述

预编译指的是js引擎预先编译,它主要针对的是两个。第一个使用var关键修饰的变量会进行预编译,第二个使用 function修饰的函数会进行预编译。

执行过程

函数声明会发生预编译

调用的时候,他会去寻找对应的堆空间的函数引用

然后再将它推入执行栈中 进行执行

在执行中会打开对应的函数内的代码进行执行

当他执行完毕以后 那么gc就会将它回收(可达性)

回收过程

gc是一个垃圾回收机制(用于回收当前没有被使用的变量) 回收器

回收器

主回收器 Major gc(常用的) 副回收器 Manor gc

回收机制

标记清楚 (设置true false标志) 引用计算 (引用操作进行++)

注意事项
  • var关键词不包含赋值过程
  • 函数的预编译会比var关键词慢 如果var关键词修饰的变量和函数名同名,那么在预编译的时候函数会覆盖var。
函数支持传入参数

关键词

形参

  1. 形容的参数
  2. 不需要var
  3. 遵循变量的命名规则
  4. 不需要声明形参的数据类型(js是弱类型语言) )
  5. 当没有传实参时,默认值是undefined,不会报错

实参

  1. 实际的参数 (实际的值)
  2. 实际参数,在调用的时候传入数据,可以是任何数据
函数的参数定义
function 函数名(形参1,形参2,形参3....){
    代码块
}
在定义函数的时候,需要考虑特殊情况
函数传入的实参可变
// 函数的实参个数可变 (多传 少传)
    function fn(a, b, c) {
        console.log(a, b, c)
    }
    //多传实参 (避免的)
    fn(1,2,3,4)
//少传实参 默认没传的参数的值为undefined
fn(1)
return 关键词

return关键词是用于返回值的,默认函数没有return的情况下返回的值为undefined 返回函数执行后的结果,在函数的调用位置 会结束函数的执行,遇到return后,即使后面还有别的js语句,也不会执行了交回函数的执行权

注意事项
  • return关键词用于返回对应的function的值,默认没有return返回undefined
  • return 关键词用于返回对应的fu
  • return会退出当前的function执行,function内的后续代码不再执行
  • return 结束当前function ,throw new error是结束当前的执行程序
  • break (用于跳出循环代码块或switch代码块) 和 continue (跳过本次循环)

arguments

arguments是一个伪数组(存储多个值的一个列表),主要是接收对应的传入的实参。它是一个内置对象。它存在于function中。

arguments的特点
  • arguments存在于function中 (只能在function里面使用)
  • arguments的长度通过length属性来获取 (arguments.length 获取长度)
  • arguments具备下标,通过下标可以访问对应的arguments里 面的元素(下标从0开始 到arguments.length-1结束)
  • 如果使用arguments来获取实参,那么对应的形参就不需要定义
作用域及作用域链
作用域

一个变量的作用范围称为作用域

作用域的划分

全局变量和局部变量的分界线,以函数为界

全局作用域
  1. 在函数外声明
  2. 全局和局部都可以访问全局声明
  3. 在函数内部声明变量不加var,就是全局变量,不推荐使用
局部作用域
  1. 在函数体内加var声明的变量
  2. 只有在局部才可以访问,也就是在函数内部
  3. 形参是局部变量

全局作用域可以在全局访问 局部作用域只能在局部访问 外部不能访问

作用域链

根据作用域查找对应的变量的过程称为作用域链

事件的简单理解:

用户行为事件:

  • onclick单击事件

  • ondblclick双击事件

  • onfocus获取光标事件

  • onblur失去光标事件

  • window.onload页面加载完成后才执行

  • onmousedown鼠标按下

  • onmouseup鼠标抬起

  • onmouseover鼠标移入

  • onmouseout鼠标移出

【注】鼠标在父元素和子元素之间互相移入移出 会触发

  • onmouseenter鼠标移入
  • onmouseleave鼠标移出

【注】鼠标在父元素和子元素之间互相移入移出 不会触发

  • onmousemove鼠标移动
事件驱动
  • 利用dom操作中的事件来执行对应的方法

  • 获取dom元素

      document.getElementById(id选择器名字) //根据id获取元素
    
  • 获取input框的值 value属性

    <!-- 使用事件驱动 onclick 点击事件
    当你点击按钮的时候 自动执行handler函数 事件驱动
    --
    >
    <button onclick="handler()">获取input框的值</button>
    <input type="text" id="input">
    <script>
        function handler(){
            //获取input框
            var input = document.getElementById('input')
            //打印input框的值
            console.log(input.value)
        }
    </script>
    
递归 (Ologn)

递归是一个基础算法,它可以完成任何循环可以完成的操作。

递归的用途(可以在不知道层级的情况下去走到底)

  • 文件目录遍历
  • DFS查找
  • 多级对象分析合并
  • 深拷贝
递归三要素
  • 找初始值(没有规律的值)

  • 找规律

  • 自己调自己 (在函数内部调用自己这个函数) 简单递归

    function fn(参数){
        if(没有规律的条件){
            //返回没有规律的值
                }else{
                //返回有规律的值 自己调用自己
            }
        }