06-JavaScript函数
2019-04-12 本文已影响0人
七分之二十四
JavaScript函数
-
函数是专门用于封装代码的,函数是一段可以随时被反复执行的代码块
-
函数格式
function 函数名称(形参列表){ 被封装的代码; }
-
使用函数的好处
- 冗余代码变少了
- 需求变更,需要修改的代码变少了
-
函数的注意点
- 一个函数可以有形参也可以没有形参(零个或多个)
- 一个函数可以有返回值也可以没有返回值
- 函数没有通过return明确返回值,默认返回undefined
- return的作用和break相似,所以return后面不能编写任何语句(永远执行不到)
- break作用是立即结束switch语句或者循环语句
- return作用立即结束当前所在函数
- 调用函数时实参的个数和形参的个数可以不相同
- JavaScript中的函数和数组一样,都是引用数据类型(对象类型)
- 其他编程语言中函数是不可以嵌套定义的,但是在JavaScript中函数可以嵌套定义
函数定义步骤
- 书写函数的固定格式
- 给函数起一个有意义的名称
- 提升代码的阅读性
- 函数名称也是标识符的一种,所以也需要遵守标识符的命名规则和规范
- 确定函数的形参列表
- 将需要封装的代码拷贝到{}中
- 确定函数的返回值
- 可以通过return 数据;的格式将函数中计算的结果返回给函数的调用者
函数arguments
- 因为console.log();也是通过()来调用的,所以log也是一个函数
- log函数的特点:可以接收1个或多个参数
- log函数可以接收1个或多个参数内部的实现原理就用到了arguments
- arguments的作用:保存所有传递给函数的实参
- 每个函数都用一个叫arguments的东西
- arguments其实是一个伪数组
函数扩展运算符
- 扩展运算符在等号左边,将剩余的数据打包到一个新的数组中
只能写在最后
- 扩展运算符在等号右边,将数组中的数据解开
- 扩展运算符在函数的形参列表中,将传递给函数的所有实参打包到一个数组中
函数形参默认值
- 在ES6之前可以通过逻辑运算符来给形参指定默认值
- 格式:条件A || 条件B
- 如果条件A成立,那么就会返回条件A,如果条件A不成立,无论条件B是否成立,都会返回条件B
- 从ES6开始,可以直接在形参后面通过=指定默认值
- ES6开始的默认值还可以从其他的函数中获取
匿名函数
- 匿名函数就是没有名称的函数
- 匿名函数不能够只定义不使用
- 匿名函数的应用场景
- 作为其他函数的参数
- 作为其他函数的返回值
- 作为一个立即执行的函数
如果想让匿名函数立即执行,那么必须使用()将函数的定义包裹起来
箭头函数ES6
-
箭头函数是
ES6
中新增的一种定义函数的格式 -
目的就是为了简化定义函数的代码
-
ES6之前定义函数的格式
function 函数名称(形参列表){ 需要封装的代码; } let 函数名称 = function(形参列表){ 需要封装的代码; }
-
从ES6开始定义函数的格式
let 函数名称 = (形参列表) =>{ 需要封装的代码; }
-
箭头函数的注意点
- 在箭头函数中如果只有一个参数,那么()可以省略
- 在箭头函数中如果{}中只有一句代码,那么{}也可以省略
函数中变量作用域
- 在JavaScript中{}外面的作用域,我们称之为全局作用域
- 在JavaScript中函数后面的{}中的作用域,我们称之为"局部作用域"
- 在ES6中只要{}没有和函数结合在一起,那么应该称为"块级作用域"
- 块级作用域和局部作用域的区别
- 在块级作用域中通过var定义的变量是全局变量
- 在局部作用域中通过var定义的变量是局部变量
- 无论是在块级作用域还是局部作用域,省略变量前面的let或者var就会变成一个全局变量
作用域链
ES6之前
- ES6之前定义变量通过var
- ES6之前没有块级作用域,都是全局作用域和局部作用域
- ES6之前函数大括号外的都是全局作用域
- ES6之前函数大括号中的都是局部作用域
- ES6之前作用域链
- 全局作用域我们又称之为0级作用域
- 定义函数开启的作用域就是1级/2级/3级...作用域
- JavaScript会将这些作用域链接在一起形成一个链条,这个链条就是作用域链
- 除0级作用域以外,当前作用域级别等于上一级+1
- 变量在作用域链查找规则
- 现在当前找,找到就使用当前作用域找到的
- 如果当前作用域中没有找到,就去上一级作用域中查找
- 依次类推直到0级为止,如果0级作用域还没找到,就报错
ES6之后
- ES6定义变量通过let
- ES6除了全局作用域,局部作用域以外,还新增了块级作用域
- ES6虽然新增了块级作用域,但是通过let定义变量并无差异(都是局部变量)
- ES6作用域链和ES6之前差别不大,ES6之前是定义函数就会开启作用域,ES6除了定义函数会开启作用域,代码块也会开启作用域
预解析
-
浏览器在执行JS代码的时候会分成两部分操作:预解析以及逐行执行代码,也就是说浏览器不会直接执行代码, 而是加工处理之后再执行,这个加工处理的过程, 我们就称之为预解析
-
预解析规则
- 将变量声明和函数声明提升到当前作用域最前面
- 将剩余代码按照书写顺序依次放到后面
- 通过let定义的变量不会被提升(不会被预解析)
function say() { console.log('hello world'); } ES6之前的这种定义函数的格式,是会被预解析的,所以可以提前调用 var say = function() { console.log('hello world'); } 如果将函数赋值给一个var定义的变量,那么函数不会被预解析,只有变量会被预解析