JS笔记--函数
本节笔记记录JavaScript函数的陌生知识点,包括函数构造,函数参数,函数调用,闭包。
函数构造
函数表达式
JS函数可以通过一个表达式定义,表达式可以存储在变量中,变量也可作为函数使用:
1 | var x = function (a, b) {return a * b}; |
这样的函数实际上是个匿名函数(没有名称)。函数存储在变量中,通过变量名调用。
Function()构造函数
函数通过function定义,也可用js函数构造器**(function())**定义:
1 | //原写法 |
但在js中应当尽量避免使用new
自调用函数
函数表达式可以通过紧跟(),实现自动调用。不能自调用一个声明的函数,通过添加括号包裹函数来说明它是一个函数表达式:
1 | (function () { |
函数是一个对象
js函数被描述为一个对象更加准确,有属性和方法。
属性举例
name
:函数的名称属性,表示函数名称
length
:函数的长度属性,表示函数接收的参数个数
1 | function exampleFunc(param1, param2) { |
方法举例
toString()
:将函数作为一个字符串返回。
call()
: 调用一个函数,可以设置函数内部的 this
指向,并传入参数列表。
apply()
: 与 call()
类似,但参数以数组形式传入。
bind()
: 创建一个新函数,将原函数的 this
绑定到指定对象,并可预先传入部分参数。
1 | function myFunction(a, b) { return a * b;} |
函数提升(Hoisting)
提升(Hoisting)是 JavaScript 默认将当前作用域提升到前面去的行为。提升(Hoisting)是 JavaScript 默认将当前作用域提升到前面去的行为。因此,函数可以在声明之前调用:
1 | myFunction(5); |
使用表达式定义函数时无法提升。
箭头函数
箭头函数可替代传统函数定义方法,比普通函数表达式更简洁:
1
2
3
4 (参数1, 参数2, …, 参数N) => { 函数声明 }
(参数1, 参数2, …, 参数N) => 表达式(单一)
// 相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
只有一个参数时,原括号可以不写;没有参数时,则必须保留原括号:
1
2
3
4 (单一参数) => {函数声明}
单一参数 => {函数声明}
() => {函数声明}
箭头函数实例:
1 | // ES5 |
箭头函数通常用于创建匿名函数和回调函数,这样写更简洁;
使用箭头函数时,箭头函数会默认绑定为外层this的值,所以箭头函数的this和外层一样;
箭头函数不能提升,使用前先定义;
函数表达式始终是一个常量,因此使用const更安全。
函数参数
显式参数(Parameters)与隐式参数(Arguments)
函数显式参数在函数定义时列出(形参)。
函数隐式参数在函数调用时传递给函数真正的值(实参)。
默认参数
函数在调用时未提供隐式函数,参数会被默认设置为undefined:
1 | function myFunction(x, y) { |
可以为参数设置默认值:
1 | function myFunction(x, y = 10) { |
arguments 对象
js函数中有一个内置的对象arguments对象,是一个由函数参数构成的参数数组,可以通过此数组进行各种操作:
1 | //查找最大值 |
延申:js没有函数重载的功能,但可通过对arguments的元素和数组长度等方式模拟重载
传参方式
通过值传递
在函数中调用的参数是函数的隐式参数。
JavaScript 隐式参数通过值来传递:函数仅仅只是获取值。
如果函数修改参数的值,不会修改显式参数的初始值(在函数外定义),隐式参数的改变在函数外是不可见的。
通过对象传递
在JavaScript中,可以引用对象的值。
因此我们在函数内部修改对象的属性就会修改其初始的值。
修改对象属性可作用于函数外部(全局变量)。修改对象属性在函数外是可见的。
函数调用
此部分内容围绕函数的this
的初始化展开,详情参考:
JavaScript 函数调用 | 菜鸟教程 (runoob.com)
闭包
函数生命周期
普通函数在执行完毕后会将结果返回给调用者,函数内部的局部变量和参数等在函数执行结束后会被销毁,除非有其他引用指向它们;
当函数执行完成后,函数内部的局部变量会被垃圾回收机制回收,无法再被访问。
变量生命周期
全局变量的作用是全局性的;
而在函数内部声明的变量是局部性的,只在函数内部起作用。
闭包:形成函数私有的作用域
闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。
通过在函数内部设置内嵌函数,在内嵌函数中引用函数的变量,因为变量被引用着所以不会被回收,于此同时函数的其他未引用部分会被回收。
计数器闭包实例:
1 | var add = (function () { |
也可写为:
1 | function x() { |
错误写法:
1 | var add = function () { |