JavaScript函数
### 基本知识
1. 函数其实也是一个对象,函数名是访问这个函数的指针,而非调用函数**函数是对象,函数名是指针**
2. 没有重载
3. 函数声明和函数表达式,函数声明会被提前
4. 函数的length对应其参数的数量
### 函数的内部属性和方法
arguments和this
arguments是一个函数对象数组,保存传入函数的所有参数,**arguments有一个callee的属性,是一个指针,指向拥有arguments对象的函数**
#### callee
举个栗子吧 eg1
```
function factorial(num){
if(num <= 1){
return 1;
}else{
return num * factorial(num - 1);
//return num * arguments.callee(num - 1);
}
}
```
上面这个是一个阶乘的计算方法,但是呢这样写有个不好的地方,在与这个函数的执行与函数名耦合在一起了,就是说,一般的function我们可以把函数名A赋值给B,这样B也指向了这个函数。
如果把A重写了,重新指向了一个新的函数,此时并不会影响B。
但是这里的话如果把`factorial()`函数重写了
```
var factorial2 = factorial;
factorial = function(){return 0;}
```
如果factorial内部没有耦合函数名,则不影响factorial2的阶乘计算,但是很明显,当factorial重写后,factorial2指向的函数计算过程中`return num * factorial(num -1)`这个值就等于0了。
所以为了消除这样“函数的执行与函数名耦合在一起的问题,采用callee的方法来解决*callee这个指针指向拥有arguments对象的函数,即这里arguments.callee等同于当前的函数名*”
```
return num * arguments.callee(num - 1);
```
#### this
this引用的是函数当前据以执行的环境对象。
简单的例子 eg2
```
window.color = "red";
var o = {color:"blue"};
function sayColor(){
alert(this.color);
}
sayColor(); //red,this当前引用的是全局对象 window.sayColor(),此时this引用的是window对象,即this.color = window.color;
o.sayColor = sayColor;
o.sayColor(); //blue,此时this引用的对象是o,即this.color = o.color;
```
> 函数名字仅仅是一个包含指针的变量而已,因此即使在不同的执行环境中,全局的sayColor()和o.sayColor()仍然是指向同一个函数。
#### caller
在ES5中规范化了另一个函数对象的属性caller,这个属性保存着**调用当前函数的函数引用**。
eg3
```
function outer(){
inner();
}
function inner(){
console.log(inner.caller);
// inner可以用arguments.callee代替 降低耦合度
}
outer(); // 输出会显示outer的源代码
```
#### call()和apply()
这两个函数用途都是在*在特定作用域中调用函数,实际上等于设置函数体内this值。*
apply(当前运行函数的作用域,参数数组|arguments对象);
call(当前运行函数的作用域,参数1,参数2...)
```
function sum(num1,num2){
return num1 + num2;
}
function callSum1(num1,num2){
return sum.apply(this,arguments);
}
function callSum2(num1,num2){
return sum.call(this,num1,num2);
}
console.log(callSum1(10,10));
console.log(callSum2(20,20));
```
两者的区别在于传入参数的方式不一样
就上面eg2来说,可以通过call/apply的方式来改变当前函数的执行环境,扩充作用域
```
sayColor.call(this);
sayColor.call(window);
sayColor.apply(o);
// ES5 还提供了一个bind()方法
var obSayColor = sayColor.bind(o);
obSayColor();
```
ES5 还提供了一个bind()方法,创建一个函数的实例,将this值绑定传到bind()函数的值。
### 小结
- 函数是对象,函数名是指针,指向函数
- 函数的两个属性arguments this
- 函数的两个方法call() apply()以及bind()