函数

callee
arguments对象有一个名为callee的属性,callee属性是一个指针,指向拥有这个arguments对象的函数。
比较经典的阶乘例子:

function factorial(num){
  if(num <= 1){
    return 1;
  }else{
    return num * factorial(num - 1);
  }
}

上述例子用到了递归,和函数名factorial紧密耦合到一起,可以使用arguments.callee解耦。

function factorial(num){
  if(num <= 1){
    return 1;
  }else{
    return num * arguments.callee(num - 1);
  }
}

caller
函数对象属性caller保存着调用当前函数的函数引用。如果在全局作用域中调用当前函数,它的值为null.

function outer(){
  inner();
}
function inner(){
  alert(inner.caller);
}
outer();

以上代码会导致警告框显示outer()函数的源代码。因为outer()调用inner(),所以inner.caller就指向了outer()。为了实现更松散的耦合,可以通过arguments.callee.caller来访问相同点信息。

function outer(){
  inner();
}
function inner(){
  alert(arguments.callee.caller);
}
outer();

函数的属性和方法

在ECMAScript中函数也是对象,因此函数有属性和方法,每个函数都有2个属性:length和prototype。其中,length表示函数希望接收的参数的个数,如下例:

function sayName(name){
  console.info(name);
}
function sum(num1, num2){
  return num1 + num2;
}
function sayHi(){
  console.info("hi");
}
console.info(sayName.lenth);     // 1
console.info(sum.length);      // 2 
console.info(sayHi.length);      // 0

prototype

对于ECMAScript中的引用类型来说,prototype是保存它们所有实例方法的真正所在。如toString()和valueOf()等方法实际上都保存在prototype名下,只是通过各自对象的实例访问。在创建自定义引用类型以及实现继承时,prototype属性是非常重要的。prototype是不可枚举的,所以不能使用for-in。

call()apply()方法

每个函数都包含2个非继承而来的方法:apply()和call()。这2个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。

一、apply()方法接收2个参数:一个是在其运行函数的作用域,另一个是参数数组。参数数组可以是Array实例,也可以是arguments对象。

function sum(num1, num2){
  return num1 + num2;
}
function callSum1(num1, num2){
  return sum.apply(this,arguments);
}
function callSum2(num1, num2){
  return sum.apply(this,[num1,num2]);
}
console.info(callSum1(10,10));    //20
console.info(callSum2(10,10));    //20

callSum1和callSum2函数传入this(这里实际上是window,因为这两个函数是在全局作用域中调用的)作为this的值。

二、call()方法和apply()方法的作用相同,它们区别只在于接收参数的方式不同,对于call()来说,第一个this值没有变化,变化的是其余参数都直接传递给参数。就是将传入的参数逐个列出来。

function sum(num1, num2){
    return num1 + num2;
}
function callSum(num1, num2){
    return sum.call(this, num1, num2);
}
console.info(callSum(10,10));    //20

call()和apply()方法的强大之处不是传递参数,而是能够扩充函数赖以运行的作用域。看下面的例子

window.color = "red";
var o = {color:"blue"};
function sayColor(){
    console.info(this.color);
}
sayColor();                //red
sayColor.call(this);      //red    
sayColor.call(window);    //red
sayColor.call(o);         //blue
原文地址:https://www.cnblogs.com/chenxiaocai/p/5543546.html