函数的定义
定义方式有两种,函数表达式和函数声明。函数声明提升,就是说函数声明在代码执行之前会提到代码最前,所以在函数声明上下文都能调用函数。而函数表达式只会提升变量。
arguments
表示函数调用时传递的参数,是一个伪数组的对象,可以用来遍历实际的参数。arguments.callee这个接口可以指向正在执行的函数本身。递归的优化就可以使用arguments.callee指向原函数,提高函数的复用性
尾调用优化
原理: 比如我们在递归调用函数时,会造成栈存在大量的栈帧,通过尾调用可以实现栈只存在当前执行的这一个函数,节省栈空间
条件:
外函数的返回值是内函数的返回值
内函数不是一个闭包,即内函数不需要在执行时访问定义时的作用域
内函数在返回后不需要执行额外的逻辑操作
尾调用优化的应用
利用一个外函数(基础框架)返回一个内函数的返回值去优化代码
函数的作用域链
函数的活动对象(函数内部作用域,代码执行过程中一直存在)
函数的变量对象 (全局作用域,函数执行过程中才会存在)
什么是闭包
函数在定义该函数时的作用域外调用并回去访问定义时的作用域,这个函数就叫做闭包
闭包的问题——内存泄露
闭包是基于作用域链的访问相应的属性和方法的,当我们的闭包形成之后就会一直指向的外函数的活动对象(外函数的作用域),当外函数执行完之后不会自动销毁,因为闭包对外函数的引用随着闭包的存在也会一直存在,只有当闭包销毁时,外函数才会一同销毁。这就会导致我们在调用完闭包后忘记取消闭包对外函数作用域的引用,外函数一直存在,导致内存泄露
this
普通函数this指向调用当前函数的对象,如果在全局作用域下调用则this指向的是window 箭头函数this指向定义箭头函数的作用域,所以在箭头函数中super,arguments等这些接口不可用,因为this的指向不同。
call/apply/bind
相同之处都可以改变this的指向
不同之处:call和apply会执行当前函数
apply可以第二个参数可以传递一个数组作为函数的实参
call()只能枚举每一个实参,不能传数组
bind()不会执行当前函数,而是返回一个新函数
私有变量
定义一个函数,在内部定义私有属性和方法,并提供公共的接口可以访问私有。利用函数作用域与世隔绝。但构造函数有个老毛病,每次生成对象都得实例化所有得属性和方法。
静态私有变量
还是定义一个属性,与上面不同的是将公共接口定义在函数的原型对象上,在原型上共享公共方法。
模块模式
通过一个单例对象实现对私有变量和方法的控制