1.定义:具备某一功能的工具,即是数据(值),也是对象。
2.字面量声明:function() nameFunc(){ 函数体(即代码块)}
(函数表达式:不同于声明,函数表达式只表示定义了一个函数对象)
3.调用:nameFunc()
4.函数提升:字面量声明的函数会被提升到代码块的顶部,原因是执行上下文中,确定变量对象中,会将函数名准备好的同时,把函数名指向函数对象(函数对象的创建和这个确认过程是同步的,不会出现函数对象没创建,函数名没法指向的情况),这个过程发生在代码执行前,因此有函数提升(变量提升也是如此)
5.参数:形式参数(定义时的参数);实际参数(调用时传入的参数)
JS函数参数的传递是值传递,即如果传递的是引用类型,则使用的是同一个地址。
Function.prototype.arguments:一个伪数组,存放函数传入的所有实际参数,包括多出的参数,与形参会有双向绑定。(实参会都存入到形参和arguments中,改变一个另一个也会改变)
剩余参数:...参数(仅在函数定义的形式参数中...表示的是收集剩余参数,其余情况是展开运算符)
6.返回值:调用函数后得到的结果,即是返回值
用return定义,如果没定义,则返回undefined。执行上下文有一个返回值槽,return会把返回值槽的值抛给调用者,然后直接摧毁执行上下文,函数会终止,return是函数变量对象ao销毁前的最后一个操作。
7.函数作用域:函数的作用域是函数对象存在,它就存在,如果函数对象被销毁,函数作用域就被销毁。
作用域链:变量对象会有一个额外属性,指向创造该变量对象的函数
函数会有一个隐藏属性,[[scope]],指向创建该函数的变量对象
拿取变量时,先找变量对象自身,没有再通过变量对象额外属性找到创造自身的函数,再通过函数的[[scope]]找到下一个外层变量对象,依次向下查找
闭包现象:作用域链的存在,让定义在内部的函数可以通过[[scope]]访问外部函数的变量对象,且当内部函数未被销毁时,外部函数的变量对象由于被内部函数通过[[scope]]指向了,因此不会被销毁,就这样驻留在内存中(但这样极大可能导致内存泄露,即驻留了完全用不到的大数据)
8.函数类型:
普通函数:直接调用,返回结果(字面量声明),this默认绑定
构造函数:用new调用,用来创建对象实例(this会绑定给new出来的新对象)
方法函数:函数作为对象的属性,this指向调用者
箭头函数:()=>{}this继承外层作用域的this
回调函数:作为参数传递给其他函数,this默认绑定
IIFE(立即执行函数):(func(){})(),定义后立即调用,函数名只有内部能调用
9.改变this的函数实例方法:
Function.prototype.apply(对象,[实参列表])立即执行函数实例,将该函数的this绑定为输入的对象,第二个参数是实参列表(需要拆分实参数组)
Function.prototype.call(对象,实参列表)即执行函数实例,将该函数的this绑定为输入的对象,剩余的参数是实参列表
Function.prototype.bind(对象,实参列表),不执行,创建一个新函数拷贝调用的函数,但改变这个新函数的this为输入的对象。
10.函数递归:函数的内部调用自身(声明式编程的重要概念)
需要有终止条件,否则会无限递归