函数声明的方式
function
关键字- 函数表达式(匿名函数)
var 变量名 = function([形参1,形参2...形参N]){}
- 构造函数
var 变量名/函数名 = new Function('形参1', '形参2', '函数体');
函数调用
func()
func.call()
(function(){})();
new func()
- 事件调用
- 定时调用
函数类数组实参arguments
- 函数调用隐含传入上下文对象
this
和封装实参的对象arguments
- 在递归调用中用
arguments.callee
代替自身函数名可以接触函数体内代码与函数名的耦合,但会导致函数体内的this
对象被更改,同时访问arguments
是个很昂贵的操作,因为它是个很大的对象,每次递归调用时都需要重新创建,影响现代浏览器的性能,还会影响闭包。
函数预编译
函数预编译,发生在函数执行的前一刻。
- 创建 Active Object 对象,即执行期上下文。
- 寻找函数的形参和变量声明,将变量和形参名作为 AO 对象的属性名,值设定为 undefined.
- 将形参和实参相统一,即更改形参后的 undefined 为具体的形参值。
- 寻找函数中的函数声明,将函数名作为 AO 属性名,值为函数体。
- 函数声明提升优先于变量声明
- 函数初始化也会提升
1 | console.log(a); // [Function: a] |
this
指向
以函数的形式(包括普通函数、定时器函数、立即执行函数)调用时,this 的指向永远都是 window。
以方法的形式调用时,this 指向调用方法的那个对象
以构造函数的形式调用时,this 指向实例对象
以事件绑定函数的形式调用时,this 指向绑定事件的对象
使用 call 和 apply 调用时,this 指向指定的那个对象
箭头函数中 this 的指向会继承外层函数调用的 this 绑定(无论 this 绑定到什么)
1 | var name = "window"; |
call
, apply
, bind
call
func.call(thisArg, ...argArray);
- 调用一个函数,同时可以改变这个函数内部的 this 指向
- 实现继承
1 | function Father(myName, myAge) { |
apply
func.apply(thisArg, ?argArray);
- 调用一个函数,同时可以改变这个函数内部的 this 指向
- 求数组最值:
Math.max.apply(Math, array)
bind
newFunc = func.bind(thisArg, ...argArray);
bind
不会立即执行函数,而是返回指定 this 和指定实参的原函数拷贝