function类型

每个函数都是function类型的实例,函数是对象,函数名是指向对象的指针

function sum(num1,num2)
  {
  return num1+num2;
  }
//等价于
var sum=function (num1,num2)
  {
  return num1+num2;
  };
//function构造函数,解析两次第一次是常规的ECMAScript代码,第二次解析传入的字符串,影响性能故不推荐
var sum=new Function("num1","num2","return num1+num2");

函数名只是指针,类似变量,一个函数可以有多个名字

function sum(num1,num2)
  {
  return num1+num2;
  }
alert(sum(10,10));  //20
var anotherSum=sum;
alert(anotherSum(10,10));  //20
sum=null;
alert(anotherSum(10,10));  //20

函数名只是指针所以ECMAScript中没有函数重载的概念,两个同名函数后声明的会覆盖先一个声明的

function addSomeNumber()
  {
  return num+100;
  }
function addSomeNumber()
  {
  return num+200;
  }
var result=addSomeNumber(100);  //300

解析器会率先读取函数声明,并添加函数声明到执行环境中,这个过程叫做 函数声明提升,即使调用它的代码写在声明之前,整个代码也能正常工作

alert(sum(10,10));
function sum(num1,num2)
  {
  return num1+num2;
  }

而对于函数表达式则是正常的一行一行解析

alert(sum(10,10));  //"unexpected identifier"(意外标识符错误)
var sum=function (num1,num2)
  {
  return num1+num2;
  };

函数名本身就是变量,所以函数可以当作值来使用

function callSomeFunction(someFunction,someArgument)
  {
  return someFunction(someArgument);
  }
 
function add10(num)
  {
  return num+10;
  }
var result1=callSomeFunction(add10,10);
alert(result1);  //20

根据一个参数比较数组

function createComparisonFunction(propertyName)
  {
  return function(object1,object2)
    {
    var value1=object1[propertyName];
    var value2=object2[propertyName];
      if(value1<value2)
        {
        return -1;
        }
      else if(value1>value2)
        {
        return 1;
        }
      else
        {
        return 0;
        }
    };
  }
var data=[{name:"Zachary",age:28},{name:"Nicholas",age:29}];
data.sort (createComparisonFunction("name"));//sort(1)则调换位置
alert(data[0].name);  //Nicholas
data.sort (createComparisonFunction("age"));
alert(data[0].name);  //Zachary

函数内部有两个特殊对象arguments和this

arguments是一个类数组对象,包含着传入数组中的所有参数,它有一个属性callee,该属性是一个指针,指向拥有这个arguments对象的函数

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

这个函数的执行与函数名factorial紧紧耦合在了一起

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

函数内部另一个特殊对象是this,this引用的是函数据以执行的环境对象,全局作用域便是window

window.color="red";
var o={color:"blue"};
function sayColor()
  {
  alert(this.color);
  }
sayColor();  //"red"
o.sayColor=sayColor;
o.sayColor();  //"blue"

ECMAScript也规范了另一个函数对象的属性caller,这个属性保存着调用当前函数的函数的引用,如果是全局作用域调用函数,它的值则为null

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

警告框显示outer()函数的源代码

function outer()
  {
  inner();
  }
function inner()
  {
  alert(arguments.callee.caller);  //减少耦合
  }
outer();

ECMAScript中函数是对象,所以函数也有方法和属性:length和prototype

length表示函数希望接收的命名参数的个数

function sayHi()
  {
  alert("Hi")
  }
alert(sayHi.length);  //0

对于ECMAScript中的引用类型,prototype是它们所有实例方法的真正所在,如toString()和valueOf()等,ECMAScript5中prototype属性不可枚举,使用for-in无法发现

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

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

function sum(num1+num2)
  {
  return num1+num2;
  }
function callSum1(num1,num2)
  {
  return sum.apply(this,arguments);  //传入arguments对象
  }
function callSum2(num1,num2)
  {
  return sum.apply(this,[num1,num2]);  //传入数组
  }
alert(callSum1(10,10));  //20
alert(callSum2(10,10));  //20
call()方法与apply()方法作用相同,区别在于接收参数的方式不同,第一个参数this不变,第二个参数必须逐个列举出来
function sum(num1+num2)
  {
  return num1+num2;
  }
function callSum(num1,num2)
  {
  return sum.call(this,num1,num2);
  }

传递参数并非apply()call()真正的永武之地,它们还能扩充函数的作用域,使对象不需要与方法有任何耦合关系

window.color="red";
var o={color:"blue"};
function sayColor()
  {
  alert(this.color);
  }
sayColor();  //red
sayColor.call(this);  //red
sayColor.call(window);  //red
sayColor.call(0);  //blue
ECMAScript5还定义了bind(),这个方法会创建一个函数的实例,绑定作用域,看例子
window.color="red";
var o={color:"blue"};
function sayColor()
  {
  alert(this.color);
  }
var objectSayColor=sayColor.bind(o);
objectSayColor();  //blue

每个函数继承的toLocaleString()和toString()还有valueOf()方法始终返回函数的代码,返回代码的格式因浏览器而异,这些信息在调试代码时倒是很有用

----------------------------------------------------------------学习专注------------------------------------------------------------------