函数声明的方式
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 属性名,值为函数体。
- 函数声明提升优先于变量声明
- 函数初始化也会提升
console.log(a); // [Function: a]
var a = 1;
console.log(a); // 1
function a() {}
console.log(a); // 1
function b(a) {
console.log(a); // [Function: a]
var a = 2;
console.log(a); // 2
function a() {}
console.log(a); // 2
}
b(3);
this
指向
-
以函数的形式(包括普通函数、定时器函数、立即执行函数)调用时,this 的指向永远都是 window。
-
以方法的形式调用时,this 指向调用方法的那个对象
-
以构造函数的形式调用时,this 指向实例对象
-
以事件绑定函数的形式调用时,this 指向绑定事件的对象
-
使用 call 和 apply 调用时,this 指向指定的那个对象
-
箭头函数中 this 的指向会继承外层函数调用的 this 绑定(无论 this 绑定到什么)
var name = "window";
var obj = {
name: "obj",
arrowFunc: () => {
console.log(this, this.name);
},
func: function () {
console.log(this, this.name);
},
};
function func() {
console.log(this, this.name);
}
// Window "window" || Object "obj" || Window "window"
func() || obj.func() || obj.arrowFunc();
call
, apply
, bind
call
func.call(thisArg, ...argArray);
- 调用一个函数,同时可以改变这个函数内部的 this 指向
- 实现继承
function Father(myName, myAge) {
this.name = myName;
this.age = myAge;
}
function Son(myName, myAge) {
Father.call(this, myName, myAge);
}
apply
func.apply(thisArg, ?argArray);
- 调用一个函数,同时可以改变这个函数内部的 this 指向
- 求数组最值:
Math.max.apply(Math, array)
bind
newFunc = func.bind(thisArg, ...argArray);
bind
不会立即执行函数,而是返回指定 this 和指定实参的原函数拷贝